// Copyright 2020 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated file. DO NOT EDIT.

// Package recommendationengine provides access to the Recommendations AI.
//
// For product documentation, see: https://cloud.google.com/recommendations-ai/docs
//
// Creating a client
//
// Usage example:
//
//   import "google.golang.org/api/recommendationengine/v1beta1"
//   ...
//   ctx := context.Background()
//   recommendationengineService, err := recommendationengine.NewService(ctx)
//
// In this example, Google Application Default Credentials are used for authentication.
//
// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
//
// Other authentication options
//
// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
//
//   recommendationengineService, err := recommendationengine.NewService(ctx, option.WithAPIKey("AIza..."))
//
// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource:
//
//   config := &oauth2.Config{...}
//   // ...
//   token, err := config.Exchange(ctx, ...)
//   recommendationengineService, err := recommendationengine.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See https://godoc.org/google.golang.org/api/option/ for details on options.
package recommendationengine // import "google.golang.org/api/recommendationengine/v1beta1"

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	googleapi "google.golang.org/api/googleapi"
	gensupport "google.golang.org/api/internal/gensupport"
	option "google.golang.org/api/option"
	internaloption "google.golang.org/api/option/internaloption"
	htransport "google.golang.org/api/transport/http"
)

// Always reference these packages, just in case the auto-generated code
// below doesn't.
var _ = bytes.NewBuffer
var _ = strconv.Itoa
var _ = fmt.Sprintf
var _ = json.NewDecoder
var _ = io.Copy
var _ = url.Parse
var _ = gensupport.MarshalJSON
var _ = googleapi.Version
var _ = errors.New
var _ = strings.Replace
var _ = context.Canceled
var _ = internaloption.WithDefaultEndpoint

const apiId = "recommendationengine:v1beta1"
const apiName = "recommendationengine"
const apiVersion = "v1beta1"
const basePath = "https://recommendationengine.googleapis.com/"
const mtlsBasePath = "https://recommendationengine.mtls.googleapis.com/"

// OAuth2 scopes used by this API.
const (
	// View and manage your data across Google Cloud Platform services
	CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
)

// NewService creates a new Service.
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
	scopesOption := option.WithScopes(
		"https://www.googleapis.com/auth/cloud-platform",
	)
	// NOTE: prepend, so we don't override user-specified scopes.
	opts = append([]option.ClientOption{scopesOption}, opts...)
	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
	opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath))
	client, endpoint, err := htransport.NewClient(ctx, opts...)
	if err != nil {
		return nil, err
	}
	s, err := New(client)
	if err != nil {
		return nil, err
	}
	if endpoint != "" {
		s.BasePath = endpoint
	}
	return s, nil
}

// New creates a new Service. It uses the provided http.Client for requests.
//
// Deprecated: please use NewService instead.
// To provide a custom HTTP client, use option.WithHTTPClient.
// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
func New(client *http.Client) (*Service, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	s := &Service{client: client, BasePath: basePath}
	s.Projects = NewProjectsService(s)
	return s, nil
}

type Service struct {
	client    *http.Client
	BasePath  string // API endpoint base URL
	UserAgent string // optional additional User-Agent fragment

	Projects *ProjectsService
}

func (s *Service) userAgent() string {
	if s.UserAgent == "" {
		return googleapi.UserAgent
	}
	return googleapi.UserAgent + " " + s.UserAgent
}

func NewProjectsService(s *Service) *ProjectsService {
	rs := &ProjectsService{s: s}
	rs.Locations = NewProjectsLocationsService(s)
	return rs
}

type ProjectsService struct {
	s *Service

	Locations *ProjectsLocationsService
}

func NewProjectsLocationsService(s *Service) *ProjectsLocationsService {
	rs := &ProjectsLocationsService{s: s}
	rs.Catalogs = NewProjectsLocationsCatalogsService(s)
	return rs
}

type ProjectsLocationsService struct {
	s *Service

	Catalogs *ProjectsLocationsCatalogsService
}

func NewProjectsLocationsCatalogsService(s *Service) *ProjectsLocationsCatalogsService {
	rs := &ProjectsLocationsCatalogsService{s: s}
	rs.CatalogItems = NewProjectsLocationsCatalogsCatalogItemsService(s)
	rs.EventStores = NewProjectsLocationsCatalogsEventStoresService(s)
	rs.Operations = NewProjectsLocationsCatalogsOperationsService(s)
	return rs
}

type ProjectsLocationsCatalogsService struct {
	s *Service

	CatalogItems *ProjectsLocationsCatalogsCatalogItemsService

	EventStores *ProjectsLocationsCatalogsEventStoresService

	Operations *ProjectsLocationsCatalogsOperationsService
}

func NewProjectsLocationsCatalogsCatalogItemsService(s *Service) *ProjectsLocationsCatalogsCatalogItemsService {
	rs := &ProjectsLocationsCatalogsCatalogItemsService{s: s}
	return rs
}

type ProjectsLocationsCatalogsCatalogItemsService struct {
	s *Service
}

func NewProjectsLocationsCatalogsEventStoresService(s *Service) *ProjectsLocationsCatalogsEventStoresService {
	rs := &ProjectsLocationsCatalogsEventStoresService{s: s}
	rs.Operations = NewProjectsLocationsCatalogsEventStoresOperationsService(s)
	rs.Placements = NewProjectsLocationsCatalogsEventStoresPlacementsService(s)
	rs.PredictionApiKeyRegistrations = NewProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService(s)
	rs.UserEvents = NewProjectsLocationsCatalogsEventStoresUserEventsService(s)
	return rs
}

type ProjectsLocationsCatalogsEventStoresService struct {
	s *Service

	Operations *ProjectsLocationsCatalogsEventStoresOperationsService

	Placements *ProjectsLocationsCatalogsEventStoresPlacementsService

	PredictionApiKeyRegistrations *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService

	UserEvents *ProjectsLocationsCatalogsEventStoresUserEventsService
}

func NewProjectsLocationsCatalogsEventStoresOperationsService(s *Service) *ProjectsLocationsCatalogsEventStoresOperationsService {
	rs := &ProjectsLocationsCatalogsEventStoresOperationsService{s: s}
	return rs
}

type ProjectsLocationsCatalogsEventStoresOperationsService struct {
	s *Service
}

func NewProjectsLocationsCatalogsEventStoresPlacementsService(s *Service) *ProjectsLocationsCatalogsEventStoresPlacementsService {
	rs := &ProjectsLocationsCatalogsEventStoresPlacementsService{s: s}
	return rs
}

type ProjectsLocationsCatalogsEventStoresPlacementsService struct {
	s *Service
}

func NewProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService(s *Service) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService {
	rs := &ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService{s: s}
	return rs
}

type ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService struct {
	s *Service
}

func NewProjectsLocationsCatalogsEventStoresUserEventsService(s *Service) *ProjectsLocationsCatalogsEventStoresUserEventsService {
	rs := &ProjectsLocationsCatalogsEventStoresUserEventsService{s: s}
	return rs
}

type ProjectsLocationsCatalogsEventStoresUserEventsService struct {
	s *Service
}

func NewProjectsLocationsCatalogsOperationsService(s *Service) *ProjectsLocationsCatalogsOperationsService {
	rs := &ProjectsLocationsCatalogsOperationsService{s: s}
	return rs
}

type ProjectsLocationsCatalogsOperationsService struct {
	s *Service
}

// GoogleApiHttpBody: Message that represents an arbitrary HTTP body. It
// should only be used for
// payload formats that can't be represented as JSON, such as raw binary
// or
// an HTML page.
//
//
// This message can be used both in streaming and non-streaming API
// methods in
// the request as well as the response.
//
// It can be used as a top-level request field, which is convenient if
// one
// wants to extract parameters from either the URL or HTTP template into
// the
// request fields and also want access to the raw HTTP body.
//
// Example:
//
//     message GetResourceRequest {
//       // A unique request id.
//       string request_id = 1;
//
//       // The raw HTTP body is bound to this field.
//       google.api.HttpBody http_body = 2;
//     }
//
//     service ResourceService {
//       rpc GetResource(GetResourceRequest) returns
// (google.api.HttpBody);
//       rpc UpdateResource(google.api.HttpBody) returns
//       (google.protobuf.Empty);
//     }
//
// Example with streaming methods:
//
//     service CaldavService {
//       rpc GetCalendar(stream google.api.HttpBody)
//         returns (stream google.api.HttpBody);
//       rpc UpdateCalendar(stream google.api.HttpBody)
//         returns (stream google.api.HttpBody);
//     }
//
// Use of this type only changes how the request and response bodies
// are
// handled, all other features will continue to work unchanged.
type GoogleApiHttpBody struct {
	// ContentType: The HTTP Content-Type header value specifying the
	// content type of the body.
	ContentType string `json:"contentType,omitempty"`

	// Data: The HTTP request/response body as raw binary.
	Data string `json:"data,omitempty"`

	// Extensions: Application specific response metadata. Must be set in
	// the first response
	// for streaming APIs.
	Extensions []googleapi.RawMessage `json:"extensions,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "ContentType") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ContentType") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleApiHttpBody) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleApiHttpBody
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1alphaRejoinCatalogMetadata: Metadata
// for TriggerCatalogRejoin method.
type GoogleCloudRecommendationengineV1alphaRejoinCatalogMetadata struct {
}

// GoogleCloudRecommendationengineV1alphaRejoinCatalogResponse: Response
// message for TriggerCatalogRejoin method.
type GoogleCloudRecommendationengineV1alphaRejoinCatalogResponse struct {
	// RejoinedUserEventsCount: Number of user events that were joined with
	// latest catalog items.
	RejoinedUserEventsCount int64 `json:"rejoinedUserEventsCount,omitempty,string"`

	// ForceSendFields is a list of field names (e.g.
	// "RejoinedUserEventsCount") to unconditionally include in API
	// requests. By default, fields with empty values are omitted from API
	// requests. However, any non-pointer, non-interface field appearing in
	// ForceSendFields will be sent to the server regardless of whether the
	// field is empty or not. This may be used to include empty fields in
	// Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "RejoinedUserEventsCount")
	// to include in API requests with the JSON null value. By default,
	// fields with empty values are omitted from API requests. However, any
	// field with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1alphaRejoinCatalogResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1alphaRejoinCatalogResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1alphaTuningMetadata: Metadata
// associated with a tune operation.
type GoogleCloudRecommendationengineV1alphaTuningMetadata struct {
	// RecommendationModel: The resource name of the recommendation model
	// that this tune applies
	// to.
	// Format:
	// projects/{project_number}/locations/{location_id}/catalogs
	// /{catalog_id}/eventStores/{event_store_id}/recommendationModels/{recom
	// mendation_model_id}
	RecommendationModel string `json:"recommendationModel,omitempty"`

	// ForceSendFields is a list of field names (e.g. "RecommendationModel")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "RecommendationModel") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1alphaTuningMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1alphaTuningMetadata
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1alphaTuningResponse: Response
// associated with a tune operation.
type GoogleCloudRecommendationengineV1alphaTuningResponse struct {
}

// GoogleCloudRecommendationengineV1beta1BigQuerySource: BigQuery source
// import data from.
type GoogleCloudRecommendationengineV1beta1BigQuerySource struct {
	// DataSchema: Optional. The schema to use when parsing the data from
	// the source.
	//
	// Supported values for catalog imports:
	//
	//  1: "catalog_recommendations_ai" using
	//
	// https://cloud.google.com/recommendations-ai/docs/upload-catalog#json
	//    (Default for catalogItems.import)
	//
	//  2: "catalog_merchant_center" using
	//
	// https://cloud.google.com/recommendations-ai/docs/upload-catalog#mc
	//
	// Su
	// pported values for user event imports:
	//
	//  1: "user_events_recommendations_ai" using
	//
	// https://cloud.google.com/recommendations-ai/docs/manage-user-events#import
	//  (Default for userEvents.import)
	DataSchema string `json:"dataSchema,omitempty"`

	// DatasetId: Required. The BigQuery data set to copy the data from.
	DatasetId string `json:"datasetId,omitempty"`

	// GcsStagingDir: Optional. Intermediate Cloud Storage directory used
	// for the import. Can be specified
	// if one wants to have the BigQuery export to a specific Cloud
	// Storage
	// directory.
	GcsStagingDir string `json:"gcsStagingDir,omitempty"`

	// ProjectId: Optional. The project id (can be project # or id) that the
	// BigQuery source is in. If
	// not specified, inherits the project id from the parent request.
	ProjectId string `json:"projectId,omitempty"`

	// TableId: Required. The BigQuery table to copy the data from.
	TableId string `json:"tableId,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DataSchema") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DataSchema") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1BigQuerySource) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1BigQuerySource
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1Catalog: The catalog
// configuration.
// Next ID: 5.
type GoogleCloudRecommendationengineV1beta1Catalog struct {
	// CatalogItemLevelConfig: Required. The catalog item level
	// configuration.
	CatalogItemLevelConfig *GoogleCloudRecommendationengineV1beta1CatalogItemLevelConfig `json:"catalogItemLevelConfig,omitempty"`

	// DefaultEventStoreId: Required. The id of the default event store.
	DefaultEventStoreId string `json:"defaultEventStoreId,omitempty"`

	// DisplayName: Required. The catalog display name.
	DisplayName string `json:"displayName,omitempty"`

	// Name: The fully qualified resource name of the catalog.
	Name string `json:"name,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g.
	// "CatalogItemLevelConfig") to unconditionally include in API requests.
	// By default, fields with empty values are omitted from API requests.
	// However, any non-pointer, non-interface field appearing in
	// ForceSendFields will be sent to the server regardless of whether the
	// field is empty or not. This may be used to include empty fields in
	// Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CatalogItemLevelConfig")
	// to include in API requests with the JSON null value. By default,
	// fields with empty values are omitted from API requests. However, any
	// field with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1Catalog) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1Catalog
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1CatalogInlineSource: The inline
// source for the input config for ImportCatalogItems method.
type GoogleCloudRecommendationengineV1beta1CatalogInlineSource struct {
	// CatalogItems: Optional. A list of catalog items to update/create.
	// Recommended max of 10k
	// items.
	CatalogItems []*GoogleCloudRecommendationengineV1beta1CatalogItem `json:"catalogItems,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CatalogItems") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CatalogItems") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1CatalogInlineSource) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1CatalogInlineSource
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1CatalogItem: CatalogItem
// captures all metadata information of items to be recommended.
type GoogleCloudRecommendationengineV1beta1CatalogItem struct {
	// CategoryHierarchies: Required. Catalog item categories. This field is
	// repeated for supporting
	// one catalog item belonging to several parallel category
	// hierarchies.
	//
	// For example, if a shoes product belongs to both
	// ["Shoes & Accessories" -> "Shoes"] and
	// ["Sports & Fitness" -> "Athletic Clothing" -> "Shoes"], it could
	// be
	// represented as:
	//
	//      "categoryHierarchies": [
	//        { "categories": ["Shoes & Accessories", "Shoes"]},
	//        { "categories": ["Sports & Fitness", "Athletic Clothing",
	// "Shoes"] }
	//      ]
	CategoryHierarchies []*GoogleCloudRecommendationengineV1beta1CatalogItemCategoryHierarchy `json:"categoryHierarchies,omitempty"`

	// Description: Optional. Catalog item description. UTF-8 encoded string
	// with a length
	// limit of 5 KiB.
	Description string `json:"description,omitempty"`

	// Id: Required. Catalog item identifier. UTF-8 encoded string with a
	// length limit
	// of 128 bytes.
	//
	// This id must be unique among all catalog items within the same
	// catalog. It
	// should also be used when logging user events in order for the user
	// events
	// to be joined with the Catalog.
	Id string `json:"id,omitempty"`

	// ItemAttributes: Optional. Highly encouraged. Extra catalog item
	// attributes to be
	// included in the recommendation model. For example, for retail
	// products,
	// this could include the store name, vendor, style, color, etc. These
	// are
	// very strong signals for recommendation model, thus we highly
	// recommend
	// providing the item attributes here.
	ItemAttributes *GoogleCloudRecommendationengineV1beta1FeatureMap `json:"itemAttributes,omitempty"`

	// ItemGroupId: Optional. Variant group identifier for prediction
	// results. UTF-8 encoded
	// string with a length limit of 128 bytes.
	//
	// This field must be enabled before it can be used.
	// [Learn
	// more](/recommendations-ai/docs/catalog#item-group-id).
	ItemGroupId string `json:"itemGroupId,omitempty"`

	// LanguageCode: Optional. Deprecated. The model automatically detects
	// the text language. Your
	// catalog can include text in different languages, but
	// duplicating
	// catalog items to provide text in multiple languages can result
	// in
	// degraded model performance.
	LanguageCode string `json:"languageCode,omitempty"`

	// ProductMetadata: Optional. Metadata specific to retail products.
	ProductMetadata *GoogleCloudRecommendationengineV1beta1ProductCatalogItem `json:"productMetadata,omitempty"`

	// Tags: Optional. Filtering tags associated with the catalog item. Each
	// tag should
	// be a UTF-8 encoded string with a length limit of 1 KiB.
	//
	// This tag can be used for filtering recommendation results by passing
	// the
	// tag as part of the predict request filter.
	Tags []string `json:"tags,omitempty"`

	// Title: Required. Catalog item title. UTF-8 encoded string with a
	// length limit of 1
	// KiB.
	Title string `json:"title,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "CategoryHierarchies")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CategoryHierarchies") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1CatalogItem) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1CatalogItem
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1CatalogItemCategoryHierarchy:
// Category represents catalog item category hierarchy.
type GoogleCloudRecommendationengineV1beta1CatalogItemCategoryHierarchy struct {
	// Categories: Required. Catalog item categories. Each category should
	// be a UTF-8
	// encoded string with a length limit of 2 KiB.
	//
	// Note that the order in the list denotes the specificity (from least
	// to
	// most specific).
	Categories []string `json:"categories,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Categories") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Categories") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1CatalogItemCategoryHierarchy) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1CatalogItemCategoryHierarchy
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1CatalogItemLevelConfig:
// Configures what level the catalog should be uploaded with regards
// to
// how users will be send events and how predictions will be made.
type GoogleCloudRecommendationengineV1beta1CatalogItemLevelConfig struct {
	// EventItemLevel: Optional. What level of the catalog are events
	// uploaded at.
	// See
	// https://cloud.google.com/recommendations-ai/docs/catalog#catalog-levels
	// for more details.
	//
	// Possible values:
	//   "CATALOG_ITEM_LEVEL_UNSPECIFIED" - Unknown value - should never be
	// used.
	//   "VARIANT" - Catalog items are at variant level.
	//   "MASTER" - Catalog items are at master level.
	EventItemLevel string `json:"eventItemLevel,omitempty"`

	// PredictItemLevel: Optional. What level of the catalog are predictions
	// made at.
	// See
	// https://cloud.google.com/recommendations-ai/docs/catalog#catalog-levels
	// for more details.
	//
	// Possible values:
	//   "CATALOG_ITEM_LEVEL_UNSPECIFIED" - Unknown value - should never be
	// used.
	//   "VARIANT" - Catalog items are at variant level.
	//   "MASTER" - Catalog items are at master level.
	PredictItemLevel string `json:"predictItemLevel,omitempty"`

	// ForceSendFields is a list of field names (e.g. "EventItemLevel") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "EventItemLevel") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1CatalogItemLevelConfig) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1CatalogItemLevelConfig
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1CreatePredictionApiKeyRegistrati
// onRequest: Request message for the
// `CreatePredictionApiKeyRegistration` method.
type GoogleCloudRecommendationengineV1beta1CreatePredictionApiKeyRegistrationRequest struct {
	// PredictionApiKeyRegistration: Required. The prediction API key
	// registration.
	PredictionApiKeyRegistration *GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration `json:"predictionApiKeyRegistration,omitempty"`

	// ForceSendFields is a list of field names (e.g.
	// "PredictionApiKeyRegistration") to unconditionally include in API
	// requests. By default, fields with empty values are omitted from API
	// requests. However, any non-pointer, non-interface field appearing in
	// ForceSendFields will be sent to the server regardless of whether the
	// field is empty or not. This may be used to include empty fields in
	// Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g.
	// "PredictionApiKeyRegistration") to include in API requests with the
	// JSON null value. By default, fields with empty values are omitted
	// from API requests. However, any field with an empty value appearing
	// in NullFields will be sent to the server as null. It is an error if a
	// field in this list has a non-empty value. This may be used to include
	// null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1CreatePredictionApiKeyRegistrationRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1CreatePredictionApiKeyRegistrationRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1EventDetail: User event details
// shared by all recommendation types.
type GoogleCloudRecommendationengineV1beta1EventDetail struct {
	// EventAttributes: Optional. Extra user event features to include in
	// the recommendation
	// model.
	//
	// For product recommendation, an example of extra user information
	// is
	// traffic_channel, i.e. how user arrives at the site. Users can
	// arrive
	// at the site by coming to the site directly, or coming through
	// Google
	// search, and etc.
	EventAttributes *GoogleCloudRecommendationengineV1beta1FeatureMap `json:"eventAttributes,omitempty"`

	// ExperimentIds: Optional. A list of identifiers for the independent
	// experiment groups
	// this user event belongs to. This is used to distinguish between user
	// events
	// associated with different experiment setups (e.g. using
	// Recommendation
	// Engine system, using different recommendation models).
	ExperimentIds []string `json:"experimentIds,omitempty"`

	// PageViewId: Optional. A unique id of a web page view.
	// This should be kept the same for all user events triggered from the
	// same
	// pageview. For example, an item detail page view could trigger
	// multiple
	// events as the user is browsing the page.
	// The `pageViewId` property should be kept the same for all these
	// events so
	// that they can be grouped together properly. This `pageViewId` will
	// be
	// automatically generated if using the JavaScript pixel.
	PageViewId string `json:"pageViewId,omitempty"`

	// RecommendationToken: Optional. Recommendation token included in the
	// recommendation prediction
	// response.
	//
	// This field enables accurate attribution of recommendation
	// model
	// performance.
	//
	// This token enables us to accurately attribute page view or purchase
	// back to
	// the event and the particular predict response containing
	// this
	// clicked/purchased item. If user clicks on product K in the
	// recommendation
	// results, pass the `PredictResponse.recommendationToken` property as a
	// url
	// parameter to product K's page. When recording events on product K's
	// page,
	// log the PredictResponse.recommendation_token to this
	// field.
	//
	// Optional, but highly encouraged for user events that are the result
	// of a
	// recommendation prediction query.
	RecommendationToken string `json:"recommendationToken,omitempty"`

	// ReferrerUri: Optional. The referrer url of the current page. When
	// using
	// the JavaScript pixel, this value is filled in automatically.
	ReferrerUri string `json:"referrerUri,omitempty"`

	// Uri: Optional. Complete url (window.location.href) of the user's
	// current page.
	// When using the JavaScript pixel, this value is filled in
	// automatically.
	// Maximum length 5KB.
	Uri string `json:"uri,omitempty"`

	// ForceSendFields is a list of field names (e.g. "EventAttributes") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "EventAttributes") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1EventDetail) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1EventDetail
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1FeatureMap: FeatureMap
// represents extra features that customers want to include in
// the
// recommendation model for catalogs/user events as
// categorical/numerical
// features.
type GoogleCloudRecommendationengineV1beta1FeatureMap struct {
	// CategoricalFeatures: Categorical features that can take on one of a
	// limited number of possible
	// values. Some examples would be the brand/maker of a product, or
	// country of
	// a customer.
	//
	// Feature names and values must be UTF-8 encoded strings.
	//
	// For example: `{ "colors": {"value": ["yellow", "green"]},
	//                 "sizes": {"value":["S", "M"]}`
	CategoricalFeatures map[string]GoogleCloudRecommendationengineV1beta1FeatureMapStringList `json:"categoricalFeatures,omitempty"`

	// NumericalFeatures: Numerical features. Some examples would be the
	// height/weight of a product,
	// or age of a customer.
	//
	// Feature names must be UTF-8 encoded strings.
	//
	// For example: `{ "lengths_cm": {"value":[2.3, 15.4]},
	//                 "heights_cm": {"value":[8.1, 6.4]} }`
	NumericalFeatures map[string]GoogleCloudRecommendationengineV1beta1FeatureMapFloatList `json:"numericalFeatures,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CategoricalFeatures")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CategoricalFeatures") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1FeatureMap) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1FeatureMap
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1FeatureMapFloatList: A list of
// float features.
type GoogleCloudRecommendationengineV1beta1FeatureMapFloatList struct {
	// Value: Float feature value.
	Value []float64 `json:"value,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Value") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Value") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1FeatureMapFloatList) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1FeatureMapFloatList
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1FeatureMapStringList: A list of
// string features.
type GoogleCloudRecommendationengineV1beta1FeatureMapStringList struct {
	// Value: String feature value with a length limit of 128 bytes.
	Value []string `json:"value,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Value") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Value") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1FeatureMapStringList) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1FeatureMapStringList
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1GcsSource: Google Cloud Storage
// location for input content.
// format.
type GoogleCloudRecommendationengineV1beta1GcsSource struct {
	// InputUris: Required. Google Cloud Storage URIs to input files. URI
	// can be up to
	// 2000 characters long. URIs can match the full object path (for
	// example,
	// gs://bucket/directory/object.json) or a pattern matching one or
	// more
	// files, such as gs://bucket/directory/*.json. A request can
	// contain at most 100 files, and each file can be up to 2 GB.
	// See
	// [Importing catalog
	// information](/recommendations-ai/docs/upload-catalog)
	// for the expected file format and setup instructions.
	InputUris []string `json:"inputUris,omitempty"`

	// JsonSchema: Optional. The schema to use when parsing the data from
	// the source.
	//
	// Supported values for catalog imports:
	//
	//  1: "catalog_recommendations_ai" using
	//
	// https://cloud.google.com/recommendations-ai/docs/upload-catalog#json
	//    (Default for catalogItems.import)
	//
	//  2: "catalog_merchant_center" using
	//
	// https://cloud.google.com/recommendations-ai/docs/upload-catalog#mc
	//
	// Su
	// pported values for user events imports:
	//
	//  1: "user_events_recommendations_ai" using
	//
	// https://cloud.google.com/recommendations-ai/docs/manage-user-events#import
	//  (Default for userEvents.import)
	JsonSchema string `json:"jsonSchema,omitempty"`

	// ForceSendFields is a list of field names (e.g. "InputUris") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "InputUris") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1GcsSource) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1GcsSource
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdRe
// sponse: Response message for GetCatalogItemsWithItemGroupId method.
type GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdResponse struct {
	// CanonicalCatalogItem: The canonical catalog item representing all
	// items associated with the item
	// group id.
	CanonicalCatalogItem *GoogleCloudRecommendationengineV1beta1CatalogItem `json:"canonicalCatalogItem,omitempty"`

	// CatalogItems: The list of catalog items associated with the item
	// group id.
	CatalogItems []*GoogleCloudRecommendationengineV1beta1CatalogItem `json:"catalogItems,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g.
	// "CanonicalCatalogItem") to unconditionally include in API requests.
	// By default, fields with empty values are omitted from API requests.
	// However, any non-pointer, non-interface field appearing in
	// ForceSendFields will be sent to the server regardless of whether the
	// field is empty or not. This may be used to include empty fields in
	// Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CanonicalCatalogItem") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1Image: Catalog item
// thumbnail/detail image.
type GoogleCloudRecommendationengineV1beta1Image struct {
	// Height: Optional. Height of the image in number of pixels.
	Height int64 `json:"height,omitempty"`

	// Uri: Required. URL of the image with a length limit of 5 KiB.
	Uri string `json:"uri,omitempty"`

	// Width: Optional. Width of the image in number of pixels.
	Width int64 `json:"width,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Height") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Height") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1Image) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1Image
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ImportCatalogItemsRequest:
// Request message for Import methods.
type GoogleCloudRecommendationengineV1beta1ImportCatalogItemsRequest struct {
	// ErrorsConfig: Optional. The desired location of errors incurred
	// during the Import.
	ErrorsConfig *GoogleCloudRecommendationengineV1beta1ImportErrorsConfig `json:"errorsConfig,omitempty"`

	// InputConfig: Required. The desired input location of the data.
	InputConfig *GoogleCloudRecommendationengineV1beta1InputConfig `json:"inputConfig,omitempty"`

	// RequestId: Optional. Unique identifier provided by client, within the
	// ancestor
	// dataset scope. Ensures idempotency and used for request
	// deduplication.
	// Server-generated if unspecified. Up to 128 characters long. This
	// is
	// returned as google.longrunning.Operation.name in the response.
	RequestId string `json:"requestId,omitempty"`

	// UpdateMask: Optional. Indicates which fields in the provided imported
	// 'items' to update. If not
	// set, will by default update all fields.
	UpdateMask string `json:"updateMask,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ErrorsConfig") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ErrorsConfig") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ImportCatalogItemsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ImportCatalogItemsRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ImportCatalogItemsResponse:
// Response of the ImportCatalogItemsRequest. If the long
// running
// operation is done, then this message is returned by
// the
// google.longrunning.Operations.response field if the operation was
// successful.
type GoogleCloudRecommendationengineV1beta1ImportCatalogItemsResponse struct {
	// ErrorSamples: A sample of errors encountered while processing the
	// request.
	ErrorSamples []*GoogleRpcStatus `json:"errorSamples,omitempty"`

	// ErrorsConfig: Echoes the destination for the complete errors in the
	// request if set.
	ErrorsConfig *GoogleCloudRecommendationengineV1beta1ImportErrorsConfig `json:"errorsConfig,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ErrorSamples") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ErrorSamples") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ImportCatalogItemsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ImportCatalogItemsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ImportErrorsConfig:
// Configuration of destination for Import related errors.
type GoogleCloudRecommendationengineV1beta1ImportErrorsConfig struct {
	// GcsPrefix: Google Cloud Storage path for import errors. This must be
	// an empty,
	// existing Cloud Storage bucket. Import errors will be written to a
	// file in
	// this bucket, one per line, as a JSON-encoded
	// `google.rpc.Status` message.
	GcsPrefix string `json:"gcsPrefix,omitempty"`

	// ForceSendFields is a list of field names (e.g. "GcsPrefix") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "GcsPrefix") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ImportErrorsConfig) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ImportErrorsConfig
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ImportMetadata: Metadata
// related to the progress of the Import operation. This will
// be
// returned by the google.longrunning.Operation.metadata field.
type GoogleCloudRecommendationengineV1beta1ImportMetadata struct {
	// CreateTime: Operation create time.
	CreateTime string `json:"createTime,omitempty"`

	// FailureCount: Count of entries that encountered errors while
	// processing.
	FailureCount int64 `json:"failureCount,omitempty,string"`

	// OperationName: Name of the operation.
	OperationName string `json:"operationName,omitempty"`

	// RequestId: Id of the request / operation. This is parroting back the
	// requestId that
	// was passed in the request.
	RequestId string `json:"requestId,omitempty"`

	// SuccessCount: Count of entries that were processed successfully.
	SuccessCount int64 `json:"successCount,omitempty,string"`

	// UpdateTime: Operation last update time. If the operation is done,
	// this is also the
	// finish time.
	UpdateTime string `json:"updateTime,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CreateTime") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CreateTime") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ImportMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ImportMetadata
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ImportUserEventsRequest:
// Request message for the ImportUserEvents request.
type GoogleCloudRecommendationengineV1beta1ImportUserEventsRequest struct {
	// ErrorsConfig: Optional. The desired location of errors incurred
	// during the Import.
	ErrorsConfig *GoogleCloudRecommendationengineV1beta1ImportErrorsConfig `json:"errorsConfig,omitempty"`

	// InputConfig: Required. The desired input location of the data.
	InputConfig *GoogleCloudRecommendationengineV1beta1InputConfig `json:"inputConfig,omitempty"`

	// RequestId: Optional. Unique identifier provided by client, within the
	// ancestor
	// dataset scope. Ensures idempotency for expensive long running
	// operations.
	// Server-generated if unspecified. Up to 128 characters long. This
	// is
	// returned as google.longrunning.Operation.name in the response. Note
	// that
	// this field must not be set if the desired input config
	// is
	// catalog_inline_source.
	RequestId string `json:"requestId,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ErrorsConfig") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ErrorsConfig") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ImportUserEventsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ImportUserEventsRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ImportUserEventsResponse:
// Response of the ImportUserEventsRequest. If the long
// running
// operation was successful, then this message is returned by
// the
// google.longrunning.Operations.response field if the operation was
// successful.
type GoogleCloudRecommendationengineV1beta1ImportUserEventsResponse struct {
	// ErrorSamples: A sample of errors encountered while processing the
	// request.
	ErrorSamples []*GoogleRpcStatus `json:"errorSamples,omitempty"`

	// ErrorsConfig: Echoes the destination for the complete errors if this
	// field was set in
	// the request.
	ErrorsConfig *GoogleCloudRecommendationengineV1beta1ImportErrorsConfig `json:"errorsConfig,omitempty"`

	// ImportSummary: Aggregated statistics of user event import status.
	ImportSummary *GoogleCloudRecommendationengineV1beta1UserEventImportSummary `json:"importSummary,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ErrorSamples") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ErrorSamples") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ImportUserEventsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ImportUserEventsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1InputConfig: The input config
// source.
type GoogleCloudRecommendationengineV1beta1InputConfig struct {
	// BigQuerySource: BigQuery input source.
	BigQuerySource *GoogleCloudRecommendationengineV1beta1BigQuerySource `json:"bigQuerySource,omitempty"`

	// CatalogInlineSource: The Inline source for the input content for
	// Catalog items.
	CatalogInlineSource *GoogleCloudRecommendationengineV1beta1CatalogInlineSource `json:"catalogInlineSource,omitempty"`

	// GcsSource: Google Cloud Storage location for the input content.
	GcsSource *GoogleCloudRecommendationengineV1beta1GcsSource `json:"gcsSource,omitempty"`

	// UserEventInlineSource: The Inline source for the input content for
	// UserEvents.
	UserEventInlineSource *GoogleCloudRecommendationengineV1beta1UserEventInlineSource `json:"userEventInlineSource,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BigQuerySource") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BigQuerySource") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1InputConfig) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1InputConfig
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse:
// Response message for ListCatalogItems method.
type GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse struct {
	// CatalogItems: The catalog items.
	CatalogItems []*GoogleCloudRecommendationengineV1beta1CatalogItem `json:"catalogItems,omitempty"`

	// NextPageToken: If empty, the list is complete. If nonempty, the token
	// to pass to the next
	// request's ListCatalogItemRequest.page_token.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "CatalogItems") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CatalogItems") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ListCatalogsResponse: Response
// for ListCatalogs method.
type GoogleCloudRecommendationengineV1beta1ListCatalogsResponse struct {
	// Catalogs: Output only. All the customer's catalogs.
	Catalogs []*GoogleCloudRecommendationengineV1beta1Catalog `json:"catalogs,omitempty"`

	// NextPageToken: Pagination token, if not returned indicates the last
	// page.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "Catalogs") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Catalogs") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ListCatalogsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ListCatalogsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistration
// sResponse: Response message for the
// `ListPredictionApiKeyRegistrations`.
type GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistrationsResponse struct {
	// NextPageToken: If empty, the list is complete. If nonempty, pass the
	// token to the next
	// request's `ListPredictionApiKeysRegistrationsRequest.pageToken`.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// PredictionApiKeyRegistrations: The list of registered API keys.
	PredictionApiKeyRegistrations []*GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration `json:"predictionApiKeyRegistrations,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "NextPageToken") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistrationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistrationsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ListUserEventsResponse:
// Response message for ListUserEvents method.
type GoogleCloudRecommendationengineV1beta1ListUserEventsResponse struct {
	// NextPageToken: If empty, the list is complete. If nonempty, the token
	// to pass to the next
	// request's ListUserEvents.page_token.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// UserEvents: The user events.
	UserEvents []*GoogleCloudRecommendationengineV1beta1UserEvent `json:"userEvents,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "NextPageToken") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ListUserEventsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ListUserEventsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1PredictRequest: Request message
// for Predict method.
type GoogleCloudRecommendationengineV1beta1PredictRequest struct {
	// DryRun: Optional. Use dryRun mode for this prediction query. If set
	// to true, a
	// dummy model will be used that returns arbitrary catalog items.
	// Note that the dryRun mode should only be used for testing the API, or
	// if
	// the model is not ready.
	DryRun bool `json:"dryRun,omitempty"`

	// Filter: Optional. Filter for restricting prediction results. Accepts
	// values for
	// tags and the `filterOutOfStockItems` flag.
	//
	//  * Tag expressions. Restricts predictions to items that match all of
	// the
	//    specified tags. Boolean operators `OR` and `NOT` are supported if
	// the
	//    expression is enclosed in parentheses, and must be separated from
	// the
	//    tag values by a space. `-"tagA" is also supported and is
	// equivalent to
	//    `NOT "tagA". Tag values must be double quoted UTF-8 encoded
	// strings
	//    with a size limit of 1 KiB.
	//
	//  * filterOutOfStockItems. Restricts predictions to items that do not
	// have a
	//    stockState value of OUT_OF_STOCK.
	//
	// Examples:
	//
	//  * tag=("Red" OR "Blue") tag="New-Arrival" tag=(NOT "promotional")
	//  * filterOutOfStockItems  tag=(-"promotional")
	//  * filterOutOfStockItems
	//
	// If your filter blocks all prediction results, nothing will be
	// returned. If
	// you want generic (unfiltered) popular items to be returned instead,
	// set
	// `strictFiltering` to false in `PredictRequest.params`.
	Filter string `json:"filter,omitempty"`

	// Labels: Optional. The labels for the predict request.
	//
	//  * Label keys can contain lowercase letters, digits and hyphens, must
	// start
	//    with a letter, and must end with a letter or digit.
	//  * Non-zero label values can contain lowercase letters, digits and
	// hyphens,
	//    must start with a letter, and must end with a letter or digit.
	//  * No more than 64 labels can be associated with a given
	// request.
	//
	// See https://goo.gl/xmQnxf for more information on and examples of
	// labels.
	Labels map[string]string `json:"labels,omitempty"`

	// PageSize: Optional. Maximum number of results to return per page. Set
	// this property
	// to the number of prediction results required. If zero, the service
	// will
	// choose a reasonable default.
	PageSize int64 `json:"pageSize,omitempty"`

	// PageToken: Optional. The previous PredictResponse.next_page_token.
	PageToken string `json:"pageToken,omitempty"`

	// Params: Optional. Additional domain specific parameters for the
	// predictions.
	//
	// Allowed values:
	//
	// * `returnCatalogItem`: Boolean. If set to true, the associated
	// catalogItem
	//    object will be returned in the
	//   `PredictResponse.PredictionResult.itemMetadata` object in the
	// method
	//    response.
	// * `returnItemScore`: Boolean. If set to true, the prediction 'score'
	//    corresponding to each returned item will be set in the `metadata`
	//    field in the prediction response. The given 'score' indicates the
	//    probability of an item being clicked/purchased given the user's
	// context
	//    and history.
	// * `strictFiltering`: Boolean. True by default. If set to false, the
	// service
	//    will return generic (unfiltered) popular items instead of empty if
	// your
	//    filter blocks all prediction results.
	Params googleapi.RawMessage `json:"params,omitempty"`

	// UserEvent: Required. Context about the user, what they are looking at
	// and what action
	// they took to trigger the predict request. Note that this user event
	// detail
	// won't be ingested to userEvent logs. Thus, a separate userEvent
	// write
	// request is required for event logging.
	UserEvent *GoogleCloudRecommendationengineV1beta1UserEvent `json:"userEvent,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DryRun") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DryRun") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PredictRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PredictRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1PredictResponse: Response
// message for predict method.
type GoogleCloudRecommendationengineV1beta1PredictResponse struct {
	// DryRun: True if the dryRun property was set in the request.
	DryRun bool `json:"dryRun,omitempty"`

	// ItemsMissingInCatalog: IDs of items in the request that were missing
	// from the catalog.
	ItemsMissingInCatalog []string `json:"itemsMissingInCatalog,omitempty"`

	// Metadata: Additional domain specific prediction response metadata.
	Metadata googleapi.RawMessage `json:"metadata,omitempty"`

	// NextPageToken: If empty, the list is complete. If nonempty, the token
	// to pass to the next
	// request's PredictRequest.page_token.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// RecommendationToken: A unique recommendation token. This should be
	// included in the user event
	// logs resulting from this recommendation, which enables accurate
	// attribution
	// of recommendation model performance.
	RecommendationToken string `json:"recommendationToken,omitempty"`

	// Results: A list of recommended items. The order represents the
	// ranking (from the
	// most relevant item to the least).
	Results []*GoogleCloudRecommendationengineV1beta1PredictResponsePredictionResult `json:"results,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "DryRun") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DryRun") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PredictResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PredictResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1PredictResponsePredictionResult:
//  PredictionResult represents the recommendation prediction results.
type GoogleCloudRecommendationengineV1beta1PredictResponsePredictionResult struct {
	// Id: ID of the recommended catalog item
	Id string `json:"id,omitempty"`

	// ItemMetadata: Additional item metadata / annotations.
	//
	// Possible values:
	//
	// * `catalogItem`: JSON representation of the catalogItem. Will be set
	// if
	//   `returnCatalogItem` is set to true in `PredictRequest.params`.
	// * `score`: Prediction score in double value. Will be set if
	//   `returnItemScore` is set to true in `PredictRequest.params`.
	ItemMetadata googleapi.RawMessage `json:"itemMetadata,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Id") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Id") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PredictResponsePredictionResult) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PredictResponsePredictionResult
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration:
// Registered Api Key.
type GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration struct {
	// ApiKey: The API key.
	ApiKey string `json:"apiKey,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "ApiKey") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ApiKey") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ProductCatalogItem:
// ProductCatalogItem captures item metadata specific to retail
// products.
type GoogleCloudRecommendationengineV1beta1ProductCatalogItem struct {
	// AvailableQuantity: Optional. The available quantity of the item.
	AvailableQuantity int64 `json:"availableQuantity,omitempty,string"`

	// CanonicalProductUri: Optional. Canonical URL directly linking to the
	// item detail page with a
	// length limit of 5 KiB..
	CanonicalProductUri string `json:"canonicalProductUri,omitempty"`

	// Costs: Optional. A map to pass the costs associated with the
	// product.
	//
	// For example:
	// {"manufacturing": 45.5} The profit of selling this item is computed
	// like
	// so:
	//
	// * If 'exactPrice' is provided, profit = displayPrice - sum(costs)
	// * If 'priceRange' is provided, profit = minPrice - sum(costs)
	Costs map[string]float64 `json:"costs,omitempty"`

	// CurrencyCode: Optional. Only required if the price is set. Currency
	// code for price/costs. Use
	// three-character ISO-4217 code.
	CurrencyCode string `json:"currencyCode,omitempty"`

	// ExactPrice: Optional. The exact product price.
	ExactPrice *GoogleCloudRecommendationengineV1beta1ProductCatalogItemExactPrice `json:"exactPrice,omitempty"`

	// Images: Optional. Product images for the catalog item.
	Images []*GoogleCloudRecommendationengineV1beta1Image `json:"images,omitempty"`

	// PriceRange: Optional. The product price range.
	PriceRange *GoogleCloudRecommendationengineV1beta1ProductCatalogItemPriceRange `json:"priceRange,omitempty"`

	// StockState: Optional. Online stock state of the catalog item. Default
	// is `IN_STOCK`.
	//
	// Possible values:
	//   "STOCK_STATE_UNSPECIFIED" - Default item stock status. Should never
	// be used.
	//   "IN_STOCK" - Item in stock.
	//   "OUT_OF_STOCK" - Item out of stock.
	//   "PREORDER" - Item that is in pre-order state.
	//   "BACKORDER" - Item that is back-ordered (i.e. temporarily out of
	// stock).
	StockState string `json:"stockState,omitempty"`

	// ForceSendFields is a list of field names (e.g. "AvailableQuantity")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AvailableQuantity") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ProductCatalogItem) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductCatalogItem
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1ProductCatalogItemExactPrice:
// Exact product price.
type GoogleCloudRecommendationengineV1beta1ProductCatalogItemExactPrice struct {
	// DisplayPrice: Optional. Display price of the product.
	DisplayPrice float64 `json:"displayPrice,omitempty"`

	// OriginalPrice: Optional. Price of the product without any discount.
	// If zero, by default
	// set to be the 'displayPrice'.
	OriginalPrice float64 `json:"originalPrice,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DisplayPrice") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DisplayPrice") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ProductCatalogItemExactPrice) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductCatalogItemExactPrice
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecommendationengineV1beta1ProductCatalogItemExactPrice) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductCatalogItemExactPrice
	var s1 struct {
		DisplayPrice  gensupport.JSONFloat64 `json:"displayPrice"`
		OriginalPrice gensupport.JSONFloat64 `json:"originalPrice"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.DisplayPrice = float64(s1.DisplayPrice)
	s.OriginalPrice = float64(s1.OriginalPrice)
	return nil
}

// GoogleCloudRecommendationengineV1beta1ProductCatalogItemPriceRange:
// Product price range when there are a range of prices for
// different
// variations of the same product.
type GoogleCloudRecommendationengineV1beta1ProductCatalogItemPriceRange struct {
	// Max: Required. The maximum product price.
	Max float64 `json:"max,omitempty"`

	// Min: Required. The minimum product price.
	Min float64 `json:"min,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Max") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Max") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ProductCatalogItemPriceRange) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductCatalogItemPriceRange
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecommendationengineV1beta1ProductCatalogItemPriceRange) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductCatalogItemPriceRange
	var s1 struct {
		Max gensupport.JSONFloat64 `json:"max"`
		Min gensupport.JSONFloat64 `json:"min"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Max = float64(s1.Max)
	s.Min = float64(s1.Min)
	return nil
}

// GoogleCloudRecommendationengineV1beta1ProductDetail: Detailed product
// information associated with a user event.
type GoogleCloudRecommendationengineV1beta1ProductDetail struct {
	// AvailableQuantity: Optional. Quantity of the products in stock when a
	// user event happens.
	// Optional. If provided, this overrides the available quantity in
	// Catalog for
	// this event. and can only be set if `stock_status` is set to
	// `IN_STOCK`.
	//
	// Note that if an item is out of stock, you must set the `stock_state`
	// field
	// to be `OUT_OF_STOCK`. Leaving this field unspecified / as zero is
	// not
	// sufficient to mark the item out of stock.
	AvailableQuantity int64 `json:"availableQuantity,omitempty"`

	// CurrencyCode: Optional. Currency code for price/costs. Use
	// three-character ISO-4217
	// code. Required only if originalPrice or displayPrice is set.
	CurrencyCode string `json:"currencyCode,omitempty"`

	// DisplayPrice: Optional. Display price of the product (e.g. discounted
	// price). If
	// provided, this will override the display price in Catalog for this
	// product.
	DisplayPrice float64 `json:"displayPrice,omitempty"`

	// Id: Required. Catalog item ID. UTF-8 encoded string with a length
	// limit of 128
	// characters.
	Id string `json:"id,omitempty"`

	// ItemAttributes: Optional. Extra features associated with a product in
	// the user event.
	ItemAttributes *GoogleCloudRecommendationengineV1beta1FeatureMap `json:"itemAttributes,omitempty"`

	// OriginalPrice: Optional. Original price of the product. If provided,
	// this will override
	// the original price in Catalog for this product.
	OriginalPrice float64 `json:"originalPrice,omitempty"`

	// Quantity: Optional. Quantity of the product associated with the user
	// event. For
	// example, this field will be 2 if two products are added to the
	// shopping
	// cart for `add-to-cart` event. Required for `add-to-cart`,
	// `add-to-list`,
	// `remove-from-cart`, `checkout-start`, `purchase-complete`, `refund`
	// event
	// types.
	Quantity int64 `json:"quantity,omitempty"`

	// StockState: Optional. Item stock state. If provided, this overrides
	// the stock state
	// in Catalog for items in this event.
	//
	// Possible values:
	//   "STOCK_STATE_UNSPECIFIED" - Default item stock status. Should never
	// be used.
	//   "IN_STOCK" - Item in stock.
	//   "OUT_OF_STOCK" - Item out of stock.
	//   "PREORDER" - Item that is in pre-order state.
	//   "BACKORDER" - Item that is back-ordered (i.e. temporarily out of
	// stock).
	StockState string `json:"stockState,omitempty"`

	// ForceSendFields is a list of field names (e.g. "AvailableQuantity")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AvailableQuantity") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ProductDetail) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductDetail
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecommendationengineV1beta1ProductDetail) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductDetail
	var s1 struct {
		DisplayPrice  gensupport.JSONFloat64 `json:"displayPrice"`
		OriginalPrice gensupport.JSONFloat64 `json:"originalPrice"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.DisplayPrice = float64(s1.DisplayPrice)
	s.OriginalPrice = float64(s1.OriginalPrice)
	return nil
}

// GoogleCloudRecommendationengineV1beta1ProductEventDetail:
// ProductEventDetail captures user event information specific to
// retail
// products.
type GoogleCloudRecommendationengineV1beta1ProductEventDetail struct {
	// CartId: Optional. The id or name of the associated shopping cart.
	// This id is used
	// to associate multiple items added or present in the cart before
	// purchase.
	//
	// This can only be set for `add-to-cart`,
	// `remove-from-cart`,
	// `checkout-start`, `purchase-complete`, or `shopping-cart-page-view`
	// events.
	CartId string `json:"cartId,omitempty"`

	// ListId: Required for `add-to-list` and `remove-from-list` events. The
	// id or name of
	// the list that the item is being added to or removed from. Other event
	// types
	// should not set this field.
	ListId string `json:"listId,omitempty"`

	// PageCategories: Required for `category-page-view` events. Other event
	// types should not set
	// this field.
	// The categories associated with a category page.
	// Category pages include special pages such as sales or promotions.
	// For
	// instance, a special sale page may have the category
	// hierarchy:
	// categories : ["Sales", "2017 Black Friday Deals"].
	PageCategories []*GoogleCloudRecommendationengineV1beta1CatalogItemCategoryHierarchy `json:"pageCategories,omitempty"`

	// ProductDetails: The main product details related to the event.
	//
	// This field is required for the following event types:
	//
	// * `add-to-cart`
	// * `add-to-list`
	// * `checkout-start`
	// * `detail-page-view`
	// * `purchase-complete`
	// * `refund`
	// * `remove-from-cart`
	// * `remove-from-list`
	//
	// This field is optional for the following event types:
	//
	// * `page-visit`
	// * `shopping-cart-page-view` - note that 'product_details' should be
	// set for
	//   this unless the shopping cart is empty.
	// * `search` (highly encouraged)
	//
	// In a `search` event, this field represents the products returned to
	// the end
	// user on the current page (the end user may have not finished broswing
	// the
	// whole page yet). When a new page is returned to the end user,
	// after
	// pagination/filtering/ordering even for the same query, a new SEARCH
	// event
	// with different product_details is desired. The end user may have
	// not
	// finished broswing the whole page yet.
	//
	// This field is not allowed for the following event types:
	//
	// * `category-page-view`
	// * `home-page-view`
	ProductDetails []*GoogleCloudRecommendationengineV1beta1ProductDetail `json:"productDetails,omitempty"`

	// PurchaseTransaction: Optional. A transaction represents the entire
	// purchase transaction.
	// Required for `purchase-complete` events. Optional for
	// `checkout-start`
	// events. Other event types should not set this field.
	PurchaseTransaction *GoogleCloudRecommendationengineV1beta1PurchaseTransaction `json:"purchaseTransaction,omitempty"`

	// SearchQuery: Required for `search` events. Other event types should
	// not set this field.
	// The user's search query as UTF-8 encoded text with a length limit of
	// 5 KiB.
	SearchQuery string `json:"searchQuery,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CartId") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CartId") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1ProductEventDetail) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1ProductEventDetail
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1PurchaseTransaction: A
// transaction represents the entire purchase transaction.
type GoogleCloudRecommendationengineV1beta1PurchaseTransaction struct {
	// Costs: Optional. All the costs associated with the product. These can
	// be
	// manufacturing costs, shipping expenses not borne by the end user, or
	// any
	// other costs.
	//
	// Total product cost such that
	//   profit = revenue - (sum(taxes) + sum(costs))
	// If product_cost is not set, then
	//   profit = revenue - tax - shipping - sum(CatalogItem.costs).
	//
	// If CatalogItem.cost is not specified for one of the items,
	// CatalogItem.cost
	// based profit *cannot* be calculated for this Transaction.
	Costs map[string]float64 `json:"costs,omitempty"`

	// CurrencyCode: Required. Currency code. Use three-character ISO-4217
	// code. This field
	// is not required if the event type is `refund`.
	CurrencyCode string `json:"currencyCode,omitempty"`

	// Id: Optional. The transaction ID with a length limit of 128 bytes.
	Id string `json:"id,omitempty"`

	// Revenue: Required. Total revenue or grand total associated with the
	// transaction.
	// This value include shipping, tax, or other adjustments to total
	// revenue
	// that you want to include as part of your revenue calculations. This
	// field
	// is not required if the event type is `refund`.
	Revenue float64 `json:"revenue,omitempty"`

	// Taxes: Optional. All the taxes associated with the transaction.
	Taxes map[string]float64 `json:"taxes,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Costs") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Costs") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PurchaseTransaction) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PurchaseTransaction
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudRecommendationengineV1beta1PurchaseTransaction) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudRecommendationengineV1beta1PurchaseTransaction
	var s1 struct {
		Revenue gensupport.JSONFloat64 `json:"revenue"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Revenue = float64(s1.Revenue)
	return nil
}

// GoogleCloudRecommendationengineV1beta1PurgeUserEventsMetadata:
// Metadata related to the progress of the PurgeUserEvents
// operation.
// This will be returned by the google.longrunning.Operation.metadata
// field.
type GoogleCloudRecommendationengineV1beta1PurgeUserEventsMetadata struct {
	// CreateTime: Operation create time.
	CreateTime string `json:"createTime,omitempty"`

	// OperationName: The ID of the request / operation.
	OperationName string `json:"operationName,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CreateTime") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CreateTime") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PurgeUserEventsMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PurgeUserEventsMetadata
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1PurgeUserEventsRequest: Request
// message for PurgeUserEvents method.
type GoogleCloudRecommendationengineV1beta1PurgeUserEventsRequest struct {
	// Filter: Required. The filter string to specify the events to be
	// deleted. Empty
	// string filter is not allowed. The eligible fields
	// for filtering are:
	//
	// * `eventType`: UserEvent.eventType field of type string.
	// * `eventTime`: in ISO 8601 "zulu" format.
	// * `visitorId`: field of type string. Specifying this will delete all
	//   events associated with a visitor.
	// * `userId`: field of type string. Specifying this will delete all
	// events
	//   associated with a user.
	//
	// Examples:
	//
	// * Deleting all events in a time range:
	//   `eventTime > "2012-04-23T18:25:43.511Z"
	//   eventTime < "2012-04-23T18:30:43.511Z"
	// * Deleting specific eventType in time range:
	//   `eventTime > "2012-04-23T18:25:43.511Z" eventType =
	// "detail-page-view"
	// * Deleting all events for a specific visitor:
	//   `visitorId = "visitor1024"
	//
	// The filtering fields are assumed to have an implicit AND.
	Filter string `json:"filter,omitempty"`

	// Force: Optional. The default value is false. Override this flag to
	// true to
	// actually perform the purge. If the field is not set to true, a
	// sampling of
	// events to be deleted will be returned.
	Force bool `json:"force,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Filter") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Filter") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PurgeUserEventsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PurgeUserEventsRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1PurgeUserEventsResponse:
// Response of the PurgeUserEventsRequest. If the long running operation
// is
// successfully done, then this message is returned by
// the
// google.longrunning.Operations.response field.
type GoogleCloudRecommendationengineV1beta1PurgeUserEventsResponse struct {
	// PurgedEventsCount: The total count of events purged as a result of
	// the operation.
	PurgedEventsCount int64 `json:"purgedEventsCount,omitempty,string"`

	// UserEventsSample: A sampling of events deleted (or will be deleted)
	// depending on the `force`
	// property in the request. Max of 500 items will be returned.
	UserEventsSample []*GoogleCloudRecommendationengineV1beta1UserEvent `json:"userEventsSample,omitempty"`

	// ForceSendFields is a list of field names (e.g. "PurgedEventsCount")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "PurgedEventsCount") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1PurgeUserEventsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1PurgeUserEventsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1RejoinUserEventsRequest:
// Request message for CatalogRejoin method.
type GoogleCloudRecommendationengineV1beta1RejoinUserEventsRequest struct {
	// UserEventRejoinScope: Required. The type of the catalog rejoin to
	// define the scope and range of the user
	// events to be rejoined with catalog items.
	//
	// Possible values:
	//   "USER_EVENT_REJOIN_SCOPE_UNSPECIFIED" - Rejoin catalogs with all
	// events including both joined events and
	// unjoined events.
	//   "JOINED_EVENTS" - Only rejoin catalogs with joined events.
	//   "UNJOINED_EVENTS" - Only rejoin catalogs with unjoined events.
	UserEventRejoinScope string `json:"userEventRejoinScope,omitempty"`

	// ForceSendFields is a list of field names (e.g.
	// "UserEventRejoinScope") to unconditionally include in API requests.
	// By default, fields with empty values are omitted from API requests.
	// However, any non-pointer, non-interface field appearing in
	// ForceSendFields will be sent to the server regardless of whether the
	// field is empty or not. This may be used to include empty fields in
	// Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "UserEventRejoinScope") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1RejoinUserEventsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1RejoinUserEventsRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1UserEvent: UserEvent captures
// all metadata information recommendation engine needs to
// know about how end users interact with customers' website.
type GoogleCloudRecommendationengineV1beta1UserEvent struct {
	// EventDetail: Optional. User event detailed information common across
	// different
	// recommendation types.
	EventDetail *GoogleCloudRecommendationengineV1beta1EventDetail `json:"eventDetail,omitempty"`

	// EventSource: Optional. This field should *not* be set when using
	// JavaScript pixel
	// or the Recommendations AI Tag. Defaults to
	// `EVENT_SOURCE_UNSPECIFIED`.
	//
	// Possible values:
	//   "EVENT_SOURCE_UNSPECIFIED" - Unspecified event source.
	//   "AUTOML" - The event is ingested via a javascript pixel or
	// Recommendations AI Tag
	// through automl datalayer or JS Macros.
	//   "ECOMMERCE" - The event is ingested via Recommendations AI Tag
	// through Enhanced
	// Ecommerce datalayer.
	//   "BATCH_UPLOAD" - The event is ingested via Import user events API.
	EventSource string `json:"eventSource,omitempty"`

	// EventTime: Optional. Only required for ImportUserEvents method.
	// Timestamp of user
	// event created.
	EventTime string `json:"eventTime,omitempty"`

	// EventType: Required. User event type. Allowed values are:
	//
	// * `add-to-cart` Products being added to cart.
	// * `add-to-list` Items being added to a list (shopping list,
	// favorites
	//   etc).
	// * `category-page-view` Special pages such as sale or promotion pages
	//   viewed.
	// * `checkout-start` User starting a checkout process.
	// * `detail-page-view` Products detail page viewed.
	// * `home-page-view` Homepage viewed.
	// * `page-visit` Generic page visits not included in the event types
	// above.
	// * `purchase-complete` User finishing a purchase.
	// * `refund` Purchased items being refunded or returned.
	// * `remove-from-cart` Products being removed from cart.
	// * `remove-from-list` Items being removed from a list.
	// * `search` Product search.
	// * `shopping-cart-page-view` User viewing a shopping cart.
	// * `impression` List of items displayed. Used by Google Tag Manager.
	EventType string `json:"eventType,omitempty"`

	// ProductEventDetail: Optional. Retail product specific user event
	// metadata.
	//
	// This field is required for the following event types:
	//
	// * `add-to-cart`
	// * `add-to-list`
	// * `category-page-view`
	// * `checkout-start`
	// * `detail-page-view`
	// * `purchase-complete`
	// * `refund`
	// * `remove-from-cart`
	// * `remove-from-list`
	// * `search`
	//
	// This field is optional for the following event types:
	//
	// * `page-visit`
	// * `shopping-cart-page-view` - note that 'product_event_detail' should
	// be
	//   set for this unless the shopping cart is empty.
	//
	// This field is not allowed for the following event types:
	//
	// * `home-page-view`
	ProductEventDetail *GoogleCloudRecommendationengineV1beta1ProductEventDetail `json:"productEventDetail,omitempty"`

	// UserInfo: Required. User information.
	UserInfo *GoogleCloudRecommendationengineV1beta1UserInfo `json:"userInfo,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "EventDetail") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "EventDetail") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1UserEvent) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1UserEvent
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1UserEventImportSummary: A
// summary of import result. The UserEventImportSummary summarizes
// the import status for user events.
type GoogleCloudRecommendationengineV1beta1UserEventImportSummary struct {
	// JoinedEventsCount: Count of user events imported with complete
	// existing catalog information.
	JoinedEventsCount int64 `json:"joinedEventsCount,omitempty,string"`

	// UnjoinedEventsCount: Count of user events imported, but with catalog
	// information not found
	// in the imported catalog.
	UnjoinedEventsCount int64 `json:"unjoinedEventsCount,omitempty,string"`

	// ForceSendFields is a list of field names (e.g. "JoinedEventsCount")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "JoinedEventsCount") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1UserEventImportSummary) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1UserEventImportSummary
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1UserEventInlineSource: The
// inline source for the input config for ImportUserEvents method.
type GoogleCloudRecommendationengineV1beta1UserEventInlineSource struct {
	// UserEvents: Optional. A list of user events to import. Recommended
	// max of 10k items.
	UserEvents []*GoogleCloudRecommendationengineV1beta1UserEvent `json:"userEvents,omitempty"`

	// ForceSendFields is a list of field names (e.g. "UserEvents") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "UserEvents") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1UserEventInlineSource) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1UserEventInlineSource
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudRecommendationengineV1beta1UserInfo: Information of end
// users.
type GoogleCloudRecommendationengineV1beta1UserInfo struct {
	// DirectUserRequest: Optional. Indicates if the request is made
	// directly from the end user
	// in which case the user_agent and ip_address fields can be
	// populated
	// from the HTTP request. This should *not* be set when using the
	// javascript
	// pixel. This flag should be set only if the API request is made
	// directly
	// from the end user such as a mobile app (and not if a gateway or a
	// server is
	// processing and pushing the user events).
	DirectUserRequest bool `json:"directUserRequest,omitempty"`

	// IpAddress: Optional. IP address of the user. This could be either
	// IPv4 (e.g. 104.133.9.80) or
	// IPv6 (e.g. 2001:0db8:85a3:0000:0000:8a2e:0370:7334). This should
	// *not* be
	// set when using the javascript pixel or if `direct_user_request` is
	// set.
	// Used to extract location information for personalization.
	IpAddress string `json:"ipAddress,omitempty"`

	// UserAgent: Optional. User agent as included in the HTTP header. UTF-8
	// encoded string
	// with a length limit of 1 KiB.
	//
	// This should *not* be set when using the JavaScript pixel or
	// if
	// `directUserRequest` is set.
	UserAgent string `json:"userAgent,omitempty"`

	// UserId: Optional. Unique identifier for logged-in user with a length
	// limit of 128
	// bytes. Required only for logged-in users.
	UserId string `json:"userId,omitempty"`

	// VisitorId: Required. A unique identifier for tracking visitors with a
	// length limit of
	// 128 bytes.
	//
	// For example, this could be implemented with a http cookie, which
	// should be
	// able to uniquely identify a visitor on a single device. This
	// unique
	// identifier should not change if the visitor log in/out of the
	// website.
	// Maximum length 128 bytes. Cannot be empty.
	VisitorId string `json:"visitorId,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DirectUserRequest")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DirectUserRequest") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudRecommendationengineV1beta1UserInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudRecommendationengineV1beta1UserInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleLongrunningListOperationsResponse: The response message for
// Operations.ListOperations.
type GoogleLongrunningListOperationsResponse struct {
	// NextPageToken: The standard List next-page token.
	NextPageToken string `json:"nextPageToken,omitempty"`

	// Operations: A list of operations that matches the specified filter in
	// the request.
	Operations []*GoogleLongrunningOperation `json:"operations,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "NextPageToken") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "NextPageToken") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleLongrunningListOperationsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleLongrunningListOperationsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleLongrunningOperation: This resource represents a long-running
// operation that is the result of a
// network API call.
type GoogleLongrunningOperation struct {
	// Done: If the value is `false`, it means the operation is still in
	// progress.
	// If `true`, the operation is completed, and either `error` or
	// `response` is
	// available.
	Done bool `json:"done,omitempty"`

	// Error: The error result of the operation in case of failure or
	// cancellation.
	Error *GoogleRpcStatus `json:"error,omitempty"`

	// Metadata: Service-specific metadata associated with the operation.
	// It typically
	// contains progress information and common metadata such as create
	// time.
	// Some services might not provide such metadata.  Any method that
	// returns a
	// long-running operation should document the metadata type, if any.
	Metadata googleapi.RawMessage `json:"metadata,omitempty"`

	// Name: The server-assigned name, which is only unique within the same
	// service that
	// originally returns it. If you use the default HTTP mapping,
	// the
	// `name` should be a resource name ending with
	// `operations/{unique_id}`.
	Name string `json:"name,omitempty"`

	// Response: The normal response of the operation in case of success.
	// If the original
	// method returns no data on success, such as `Delete`, the response
	// is
	// `google.protobuf.Empty`.  If the original method is
	// standard
	// `Get`/`Create`/`Update`, the response should be the resource.  For
	// other
	// methods, the response should have the type `XxxResponse`, where
	// `Xxx`
	// is the original method name.  For example, if the original method
	// name
	// is `TakeSnapshot()`, the inferred response type
	// is
	// `TakeSnapshotResponse`.
	Response googleapi.RawMessage `json:"response,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "Done") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Done") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleLongrunningOperation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleLongrunningOperation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleProtobufEmpty: A generic empty message that you can re-use to
// avoid defining duplicated
// empty messages in your APIs. A typical example is to use it as the
// request
// or the response type of an API method. For instance:
//
//     service Foo {
//       rpc Bar(google.protobuf.Empty) returns
// (google.protobuf.Empty);
//     }
//
// The JSON representation for `Empty` is empty JSON object `{}`.
type GoogleProtobufEmpty struct {
	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`
}

// GoogleRpcStatus: The `Status` type defines a logical error model that
// is suitable for
// different programming environments, including REST APIs and RPC APIs.
// It is
// used by [gRPC](https://github.com/grpc). Each `Status` message
// contains
// three pieces of data: error code, error message, and error
// details.
//
// You can find out more about this error model and how to work with it
// in the
// [API Design Guide](https://cloud.google.com/apis/design/errors).
type GoogleRpcStatus struct {
	// Code: The status code, which should be an enum value of
	// google.rpc.Code.
	Code int64 `json:"code,omitempty"`

	// Details: A list of messages that carry the error details.  There is a
	// common set of
	// message types for APIs to use.
	Details []googleapi.RawMessage `json:"details,omitempty"`

	// Message: A developer-facing error message, which should be in
	// English. Any
	// user-facing error message should be localized and sent in
	// the
	// google.rpc.Status.details field, or localized by the client.
	Message string `json:"message,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Code") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Code") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleRpcStatus) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleRpcStatus
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// method id "recommendationengine.projects.locations.catalogs.list":

type ProjectsLocationsCatalogsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists all the catalog configurations associated with the
// project.
func (r *ProjectsLocationsCatalogsService) List(parent string) *ProjectsLocationsCatalogsListCall {
	c := &ProjectsLocationsCatalogsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": Maximum number of
// results to return. If unspecified, defaults
// to 50. Max allowed value is 1000.
func (c *ProjectsLocationsCatalogsListCall) PageSize(pageSize int64) *ProjectsLocationsCatalogsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": A page token,
// received from a previous `ListCatalogs`
// call. Provide this to retrieve the subsequent page.
func (c *ProjectsLocationsCatalogsListCall) PageToken(pageToken string) *ProjectsLocationsCatalogsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsListCall) Context(ctx context.Context) *ProjectsLocationsCatalogsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/catalogs")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.list" call.
// Exactly one of
// *GoogleCloudRecommendationengineV1beta1ListCatalogsResponse or error
// will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1ListCatalogsResponse.ServerResp
// onse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1ListCatalogsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1ListCatalogsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Lists all the catalog configurations associated with the project.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.list",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "pageSize": {
	//       "description": "Optional. Maximum number of results to return. If unspecified, defaults\nto 50. Max allowed value is 1000.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "Optional. A page token, received from a previous `ListCatalogs`\ncall. Provide this to retrieve the subsequent page.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. The account resource name with an associated location.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/catalogs",
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1ListCatalogsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsCatalogsListCall) Pages(ctx context.Context, f func(*GoogleCloudRecommendationengineV1beta1ListCatalogsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

// method id "recommendationengine.projects.locations.catalogs.patch":

type ProjectsLocationsCatalogsPatchCall struct {
	s                                             *Service
	name                                          string
	googlecloudrecommendationenginev1beta1catalog *GoogleCloudRecommendationengineV1beta1Catalog
	urlParams_                                    gensupport.URLParams
	ctx_                                          context.Context
	header_                                       http.Header
}

// Patch: Updates the catalog configuration.
func (r *ProjectsLocationsCatalogsService) Patch(name string, googlecloudrecommendationenginev1beta1catalog *GoogleCloudRecommendationengineV1beta1Catalog) *ProjectsLocationsCatalogsPatchCall {
	c := &ProjectsLocationsCatalogsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecommendationenginev1beta1catalog = googlecloudrecommendationenginev1beta1catalog
	return c
}

// UpdateMask sets the optional parameter "updateMask": Indicates which
// fields in the provided 'recommendation_model' to
// update. If not set, will only update the catalog_item_level_config
// field.
func (c *ProjectsLocationsCatalogsPatchCall) UpdateMask(updateMask string) *ProjectsLocationsCatalogsPatchCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsPatchCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsPatchCall) Context(ctx context.Context) *ProjectsLocationsCatalogsPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1catalog)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.patch" call.
// Exactly one of *GoogleCloudRecommendationengineV1beta1Catalog or
// error will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1Catalog.ServerResponse.Header
// or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsPatchCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1Catalog, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1Catalog{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Updates the catalog configuration.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}",
	//   "httpMethod": "PATCH",
	//   "id": "recommendationengine.projects.locations.catalogs.patch",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "The fully qualified resource name of the catalog.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     },
	//     "updateMask": {
	//       "description": "Optional. Indicates which fields in the provided 'recommendation_model' to\nupdate. If not set, will only update the catalog_item_level_config field.",
	//       "format": "google-fieldmask",
	//       "location": "query",
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1Catalog"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1Catalog"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.catalogItems.create":

type ProjectsLocationsCatalogsCatalogItemsCreateCall struct {
	s                                                 *Service
	parent                                            string
	googlecloudrecommendationenginev1beta1catalogitem *GoogleCloudRecommendationengineV1beta1CatalogItem
	urlParams_                                        gensupport.URLParams
	ctx_                                              context.Context
	header_                                           http.Header
}

// Create: Creates a catalog item.
func (r *ProjectsLocationsCatalogsCatalogItemsService) Create(parent string, googlecloudrecommendationenginev1beta1catalogitem *GoogleCloudRecommendationengineV1beta1CatalogItem) *ProjectsLocationsCatalogsCatalogItemsCreateCall {
	c := &ProjectsLocationsCatalogsCatalogItemsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecommendationenginev1beta1catalogitem = googlecloudrecommendationenginev1beta1catalogitem
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsCatalogItemsCreateCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsCatalogItemsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsCatalogItemsCreateCall) Context(ctx context.Context) *ProjectsLocationsCatalogsCatalogItemsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsCatalogItemsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsCatalogItemsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1catalogitem)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/catalogItems")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.catalogItems.create" call.
// Exactly one of *GoogleCloudRecommendationengineV1beta1CatalogItem or
// error will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1CatalogItem.ServerResponse.Head
// er or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsCatalogItemsCreateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1CatalogItem, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1CatalogItem{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Creates a catalog item.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/catalogItems",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.catalogItems.create",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. The parent catalog resource name, such as\n\"projects/*/locations/global/catalogs/default_catalog\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/catalogItems",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1CatalogItem"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1CatalogItem"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.catalogItems.delete":

type ProjectsLocationsCatalogsCatalogItemsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Deletes a catalog item.
func (r *ProjectsLocationsCatalogsCatalogItemsService) Delete(name string) *ProjectsLocationsCatalogsCatalogItemsDeleteCall {
	c := &ProjectsLocationsCatalogsCatalogItemsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsCatalogItemsDeleteCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsCatalogItemsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsCatalogItemsDeleteCall) Context(ctx context.Context) *ProjectsLocationsCatalogsCatalogItemsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsCatalogItemsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsCatalogItemsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.catalogItems.delete" call.
// Exactly one of *GoogleProtobufEmpty or error will be non-nil. Any
// non-2xx status code is an error. Response headers are in either
// *GoogleProtobufEmpty.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsCatalogItemsDeleteCall) Do(opts ...googleapi.CallOption) (*GoogleProtobufEmpty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleProtobufEmpty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Deletes a catalog item.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/catalogItems/{catalogItemsId}",
	//   "httpMethod": "DELETE",
	//   "id": "recommendationengine.projects.locations.catalogs.catalogItems.delete",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Full resource name of catalog item, such as\n\"projects/*/locations/global/catalogs/default_catalog/catalogItems/some_catalog_item_id\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/catalogItems/.*$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleProtobufEmpty"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.catalogItems.get":

type ProjectsLocationsCatalogsCatalogItemsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets a specific catalog item.
func (r *ProjectsLocationsCatalogsCatalogItemsService) Get(name string) *ProjectsLocationsCatalogsCatalogItemsGetCall {
	c := &ProjectsLocationsCatalogsCatalogItemsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsCatalogItemsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsCatalogItemsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsCatalogItemsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsCatalogItemsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsCatalogItemsGetCall) Context(ctx context.Context) *ProjectsLocationsCatalogsCatalogItemsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsCatalogItemsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsCatalogItemsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.catalogItems.get" call.
// Exactly one of *GoogleCloudRecommendationengineV1beta1CatalogItem or
// error will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1CatalogItem.ServerResponse.Head
// er or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsCatalogItemsGetCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1CatalogItem, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1CatalogItem{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Gets a specific catalog item.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/catalogItems/{catalogItemsId}",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.catalogItems.get",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Full resource name of catalog item, such as\n\"projects/*/locations/global/catalogs/default_catalog/catalogitems/some_catalog_item_id\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/catalogItems/.*$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1CatalogItem"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.catalogItems.getGroupIdItems":

type ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// GetGroupIdItems: Method for getting the catalog items associated with
// item group id.
func (r *ProjectsLocationsCatalogsCatalogItemsService) GetGroupIdItems(parent string) *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall {
	c := &ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// ItemGroupId sets the optional parameter "itemGroupId": Required.
// Catalog item identifier for prediction results.
func (c *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall) ItemGroupId(itemGroupId string) *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall {
	c.urlParams_.Set("itemGroupId", itemGroupId)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall) Context(ctx context.Context) *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/catalogItems:groupIdItems")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.catalogItems.getGroupIdItems" call.
// Exactly one of
// *GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdR
// esponse or error will be non-nil. Any non-2xx status code is an
// error. Response headers are in either
// *GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdR
// esponse.ServerResponse.Header or (if a response was returned at all)
// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
// check whether the returned error was because http.StatusNotModified
// was returned.
func (c *ProjectsLocationsCatalogsCatalogItemsGetGroupIdItemsCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Method for getting the catalog items associated with item group id.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/catalogItems:groupIdItems",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.catalogItems.getGroupIdItems",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "itemGroupId": {
	//       "description": "Required. Catalog item identifier for prediction results.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. Parent resource name of group id item, such as\n\"projects/*/locations/global/catalogs/default_catalog\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/catalogItems:groupIdItems",
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1GetCatalogItemsWithItemGroupIdResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.catalogItems.import":

type ProjectsLocationsCatalogsCatalogItemsImportCall struct {
	s                                                               *Service
	parent                                                          string
	googlecloudrecommendationenginev1beta1importcatalogitemsrequest *GoogleCloudRecommendationengineV1beta1ImportCatalogItemsRequest
	urlParams_                                                      gensupport.URLParams
	ctx_                                                            context.Context
	header_                                                         http.Header
}

// Import: Bulk import of multiple catalog items. Request processing may
// be
// synchronous. No partial updating supported. Non-existing items will
// be
// created.
//
// Operation.response is of type ImportResponse. Note that it
// is
// possible for a subset of the items to be successfully updated.
func (r *ProjectsLocationsCatalogsCatalogItemsService) Import(parent string, googlecloudrecommendationenginev1beta1importcatalogitemsrequest *GoogleCloudRecommendationengineV1beta1ImportCatalogItemsRequest) *ProjectsLocationsCatalogsCatalogItemsImportCall {
	c := &ProjectsLocationsCatalogsCatalogItemsImportCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecommendationenginev1beta1importcatalogitemsrequest = googlecloudrecommendationenginev1beta1importcatalogitemsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsCatalogItemsImportCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsCatalogItemsImportCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsCatalogItemsImportCall) Context(ctx context.Context) *ProjectsLocationsCatalogsCatalogItemsImportCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsCatalogItemsImportCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsCatalogItemsImportCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1importcatalogitemsrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/catalogItems:import")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.catalogItems.import" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsCatalogItemsImportCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Bulk import of multiple catalog items. Request processing may be\nsynchronous. No partial updating supported. Non-existing items will be\ncreated.\n\nOperation.response is of type ImportResponse. Note that it is\npossible for a subset of the items to be successfully updated.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/catalogItems:import",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.catalogItems.import",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. \"projects/1234/locations/global/catalogs/default_catalog\"\n\nIf no updateMask is specified, requires catalogItems.create permission.\nIf updateMask is specified, requires catalogItems.update permission.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/catalogItems:import",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1ImportCatalogItemsRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.catalogItems.list":

type ProjectsLocationsCatalogsCatalogItemsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Gets a list of catalog items.
func (r *ProjectsLocationsCatalogsCatalogItemsService) List(parent string) *ProjectsLocationsCatalogsCatalogItemsListCall {
	c := &ProjectsLocationsCatalogsCatalogItemsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": A filter to apply on the
// list results.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) Filter(filter string) *ProjectsLocationsCatalogsCatalogItemsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": Maximum number of
// results to return per page. If zero, the
// service will choose a reasonable default.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) PageSize(pageSize int64) *ProjectsLocationsCatalogsCatalogItemsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The previous
// ListCatalogItemsResponse.next_page_token.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) PageToken(pageToken string) *ProjectsLocationsCatalogsCatalogItemsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsCatalogItemsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsCatalogItemsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) Context(ctx context.Context) *ProjectsLocationsCatalogsCatalogItemsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsCatalogItemsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/catalogItems")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.catalogItems.list" call.
// Exactly one of
// *GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse or
// error will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse.Server
// Response.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Gets a list of catalog items.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/catalogItems",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.catalogItems.list",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "filter": {
	//       "description": "Optional. A filter to apply on the list results.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "pageSize": {
	//       "description": "Optional. Maximum number of results to return per page. If zero, the\nservice will choose a reasonable default.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "Optional. The previous ListCatalogItemsResponse.next_page_token.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. The parent catalog resource name, such as\n\"projects/*/locations/global/catalogs/default_catalog\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/catalogItems",
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsCatalogsCatalogItemsListCall) Pages(ctx context.Context, f func(*GoogleCloudRecommendationengineV1beta1ListCatalogItemsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

// method id "recommendationengine.projects.locations.catalogs.catalogItems.patch":

type ProjectsLocationsCatalogsCatalogItemsPatchCall struct {
	s                                                 *Service
	name                                              string
	googlecloudrecommendationenginev1beta1catalogitem *GoogleCloudRecommendationengineV1beta1CatalogItem
	urlParams_                                        gensupport.URLParams
	ctx_                                              context.Context
	header_                                           http.Header
}

// Patch: Updates a catalog item. Partial updating is supported.
// Non-existing
// items will be created.
func (r *ProjectsLocationsCatalogsCatalogItemsService) Patch(name string, googlecloudrecommendationenginev1beta1catalogitem *GoogleCloudRecommendationengineV1beta1CatalogItem) *ProjectsLocationsCatalogsCatalogItemsPatchCall {
	c := &ProjectsLocationsCatalogsCatalogItemsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecommendationenginev1beta1catalogitem = googlecloudrecommendationenginev1beta1catalogitem
	return c
}

// UpdateMask sets the optional parameter "updateMask": Indicates which
// fields in the provided 'item' to update. If not
// set, will by default update all fields.
func (c *ProjectsLocationsCatalogsCatalogItemsPatchCall) UpdateMask(updateMask string) *ProjectsLocationsCatalogsCatalogItemsPatchCall {
	c.urlParams_.Set("updateMask", updateMask)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsCatalogItemsPatchCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsCatalogItemsPatchCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsCatalogItemsPatchCall) Context(ctx context.Context) *ProjectsLocationsCatalogsCatalogItemsPatchCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsCatalogItemsPatchCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsCatalogItemsPatchCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1catalogitem)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("PATCH", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.catalogItems.patch" call.
// Exactly one of *GoogleCloudRecommendationengineV1beta1CatalogItem or
// error will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1CatalogItem.ServerResponse.Head
// er or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsCatalogItemsPatchCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1CatalogItem, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1CatalogItem{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Updates a catalog item. Partial updating is supported. Non-existing\nitems will be created.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/catalogItems/{catalogItemsId}",
	//   "httpMethod": "PATCH",
	//   "id": "recommendationengine.projects.locations.catalogs.catalogItems.patch",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Full resource name of catalog item, such as\n\"projects/*/locations/global/catalogs/default_catalog/catalogItems/some_catalog_item_id\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/catalogItems/.*$",
	//       "required": true,
	//       "type": "string"
	//     },
	//     "updateMask": {
	//       "description": "Optional. Indicates which fields in the provided 'item' to update. If not\nset, will by default update all fields.",
	//       "format": "google-fieldmask",
	//       "location": "query",
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1CatalogItem"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1CatalogItem"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.operations.get":

type ProjectsLocationsCatalogsEventStoresOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation.  Clients can
// use this
// method to poll the operation result at intervals as recommended by
// the API
// service.
func (r *ProjectsLocationsCatalogsEventStoresOperationsService) Get(name string) *ProjectsLocationsCatalogsEventStoresOperationsGetCall {
	c := &ProjectsLocationsCatalogsEventStoresOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsEventStoresOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsEventStoresOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresOperationsGetCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.operations.get" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresOperationsGetCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Gets the latest state of a long-running operation.  Clients can use this\nmethod to poll the operation result at intervals as recommended by the API\nservice.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/operations/{operationsId}",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.operations.get",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "The name of the operation resource.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+/operations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.operations.list":

type ProjectsLocationsCatalogsEventStoresOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the
// request. If the
// server doesn't support this method, it returns
// `UNIMPLEMENTED`.
//
// NOTE: the `name` binding allows API services to override the
// binding
// to use different resource name schemes, such as `users/*/operations`.
// To
// override the binding, API services can add a binding such
// as
// "/v1/{name=users/*}/operations" to their service configuration.
// For backwards compatibility, the default name includes the
// operations
// collection id, however overriding users must ensure the name
// binding
// is the parent resource, without the operations collection id.
func (r *ProjectsLocationsCatalogsEventStoresOperationsService) List(name string) *ProjectsLocationsCatalogsEventStoresOperationsListCall {
	c := &ProjectsLocationsCatalogsEventStoresOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list
// filter.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) Filter(filter string) *ProjectsLocationsCatalogsEventStoresOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list
// page size.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) PageSize(pageSize int64) *ProjectsLocationsCatalogsEventStoresOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list
// page token.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) PageToken(pageToken string) *ProjectsLocationsCatalogsEventStoresOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsEventStoresOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}/operations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.operations.list" call.
// Exactly one of *GoogleLongrunningListOperationsResponse or error will
// be non-nil. Any non-2xx status code is an error. Response headers are
// in either
// *GoogleLongrunningListOperationsResponse.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header.
// Use googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Lists operations that match the specified filter in the request. If the\nserver doesn't support this method, it returns `UNIMPLEMENTED`.\n\nNOTE: the `name` binding allows API services to override the binding\nto use different resource name schemes, such as `users/*/operations`. To\noverride the binding, API services can add a binding such as\n`\"/v1/{name=users/*}/operations\"` to their service configuration.\nFor backwards compatibility, the default name includes the operations\ncollection id, however overriding users must ensure the name binding\nis the parent resource, without the operations collection id.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/operations",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.operations.list",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "filter": {
	//       "description": "The standard list filter.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "name": {
	//       "description": "The name of the operation's parent resource.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     },
	//     "pageSize": {
	//       "description": "The standard list page size.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "The standard list page token.",
	//       "location": "query",
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}/operations",
	//   "response": {
	//     "$ref": "GoogleLongrunningListOperationsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsCatalogsEventStoresOperationsListCall) Pages(ctx context.Context, f func(*GoogleLongrunningListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

// method id "recommendationengine.projects.locations.catalogs.eventStores.placements.predict":

type ProjectsLocationsCatalogsEventStoresPlacementsPredictCall struct {
	s                                                    *Service
	name                                                 string
	googlecloudrecommendationenginev1beta1predictrequest *GoogleCloudRecommendationengineV1beta1PredictRequest
	urlParams_                                           gensupport.URLParams
	ctx_                                                 context.Context
	header_                                              http.Header
}

// Predict: Makes a recommendation prediction. If using API Key based
// authentication,
// the API Key must be registered using
// the
// PredictionApiKeyRegistry
// service. [Learn
// more](/recommendations-ai/docs/setting-up#register-key).
func (r *ProjectsLocationsCatalogsEventStoresPlacementsService) Predict(name string, googlecloudrecommendationenginev1beta1predictrequest *GoogleCloudRecommendationengineV1beta1PredictRequest) *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall {
	c := &ProjectsLocationsCatalogsEventStoresPlacementsPredictCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	c.googlecloudrecommendationenginev1beta1predictrequest = googlecloudrecommendationenginev1beta1predictrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1predictrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}:predict")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.placements.predict" call.
// Exactly one of *GoogleCloudRecommendationengineV1beta1PredictResponse
// or error will be non-nil. Any non-2xx status code is an error.
// Response headers are in either
// *GoogleCloudRecommendationengineV1beta1PredictResponse.ServerResponse.
// Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1PredictResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1PredictResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Makes a recommendation prediction. If using API Key based authentication,\nthe API Key must be registered using the\nPredictionApiKeyRegistry\nservice. [Learn more](/recommendations-ai/docs/setting-up#register-key).",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/placements/{placementsId}:predict",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.placements.predict",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. Full resource name of the format:\n{name=projects/*/locations/global/catalogs/default_catalog/eventStores/default_event_store/placements/*}\nThe id of the recommendation engine placement. This id is used to identify\nthe set of models that will be used to make the prediction.\n\nWe currently support three placements with the following IDs by default:\n\n* `shopping_cart`: Predicts items frequently bought together with one or\n  more catalog items in the same shopping session. Commonly displayed after\n  `add-to-cart` events, on product detail pages, or on the shopping cart\n  page.\n\n* `home_page`: Predicts the next product that a user will most likely\n  engage with or purchase based on the shopping or viewing history of the\n  specified `userId` or `visitorId`. For example - Recommendations for you.\n\n* `product_detail`: Predicts the next product that a user will most likely\n  engage with or purchase. The prediction is based on the shopping or\n  viewing history of the specified `userId` or `visitorId` and its\n  relevance to a specified `CatalogItem`. Typically used on product detail\n  pages. For example - More items like this.\n\n* `recently_viewed_default`: Returns up to 75 items recently viewed by the\n  specified `userId` or `visitorId`, most recent ones first. Returns\n  nothing if neither of them has viewed any items yet. For example -\n  Recently viewed.\n\nThe full list of available placements can be seen at\nhttps://console.cloud.google.com/recommendation/datafeeds/default_catalog/dashboard",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+/placements/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}:predict",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1PredictRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1PredictResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsCatalogsEventStoresPlacementsPredictCall) Pages(ctx context.Context, f func(*GoogleCloudRecommendationengineV1beta1PredictResponse) error) error {
	c.ctx_ = ctx
	defer func(pt string) { c.googlecloudrecommendationenginev1beta1predictrequest.PageToken = pt }(c.googlecloudrecommendationenginev1beta1predictrequest.PageToken) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.googlecloudrecommendationenginev1beta1predictrequest.PageToken = x.NextPageToken
	}
}

// method id "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.create":

type ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall struct {
	s                                                                               *Service
	parent                                                                          string
	googlecloudrecommendationenginev1beta1createpredictionapikeyregistrationrequest *GoogleCloudRecommendationengineV1beta1CreatePredictionApiKeyRegistrationRequest
	urlParams_                                                                      gensupport.URLParams
	ctx_                                                                            context.Context
	header_                                                                         http.Header
}

// Create: Register an API key for use with predict method.
func (r *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService) Create(parent string, googlecloudrecommendationenginev1beta1createpredictionapikeyregistrationrequest *GoogleCloudRecommendationengineV1beta1CreatePredictionApiKeyRegistrationRequest) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall {
	c := &ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecommendationenginev1beta1createpredictionapikeyregistrationrequest = googlecloudrecommendationenginev1beta1createpredictionapikeyregistrationrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1createpredictionapikeyregistrationrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/predictionApiKeyRegistrations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.create" call.
// Exactly one of
// *GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration
// or error will be non-nil. Any non-2xx status code is an error.
// Response headers are in either
// *GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration.Se
// rverResponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsCreateCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Register an API key for use with predict method.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/predictionApiKeyRegistrations",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.create",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. The parent resource path.\n\"projects/*/locations/global/catalogs/default_catalog/eventStores/default_event_store\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/predictionApiKeyRegistrations",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1CreatePredictionApiKeyRegistrationRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1PredictionApiKeyRegistration"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.delete":

type ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall struct {
	s          *Service
	name       string
	urlParams_ gensupport.URLParams
	ctx_       context.Context
	header_    http.Header
}

// Delete: Unregister an apiKey from using for predict method.
func (r *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService) Delete(name string) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall {
	c := &ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("DELETE", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.delete" call.
// Exactly one of *GoogleProtobufEmpty or error will be non-nil. Any
// non-2xx status code is an error. Response headers are in either
// *GoogleProtobufEmpty.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsDeleteCall) Do(opts ...googleapi.CallOption) (*GoogleProtobufEmpty, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleProtobufEmpty{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Unregister an apiKey from using for predict method.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/predictionApiKeyRegistrations/{predictionApiKeyRegistrationsId}",
	//   "httpMethod": "DELETE",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.delete",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "Required. The API key to unregister including full resource path.\n\"projects/*/locations/global/catalogs/default_catalog/eventStores/default_event_store/predictionApiKeyRegistrations/\u003cYOUR_API_KEY\u003e\"",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+/predictionApiKeyRegistrations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleProtobufEmpty"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.list":

type ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: List the registered apiKeys for use with predict method.
func (r *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsService) List(parent string) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall {
	c := &ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// PageSize sets the optional parameter "pageSize": Maximum number of
// results to return per page. If unset, the
// service will choose a reasonable default.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) PageSize(pageSize int64) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The previous
// `ListPredictionApiKeyRegistration.nextPageToken`.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) PageToken(pageToken string) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/predictionApiKeyRegistrations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.list" call.
// Exactly one of
// *GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistratio
// nsResponse or error will be non-nil. Any non-2xx status code is an
// error. Response headers are in either
// *GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistratio
// nsResponse.ServerResponse.Header or (if a response was returned at
// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified
// to check whether the returned error was because
// http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistrationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistrationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "List the registered apiKeys for use with predict method.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/predictionApiKeyRegistrations",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.predictionApiKeyRegistrations.list",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "pageSize": {
	//       "description": "Optional. Maximum number of results to return per page. If unset, the\nservice will choose a reasonable default.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "Optional. The previous `ListPredictionApiKeyRegistration.nextPageToken`.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. The parent placement resource name such as\n\"projects/1234/locations/global/catalogs/default_catalog/eventStores/default_event_store\"",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/predictionApiKeyRegistrations",
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistrationsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsCatalogsEventStoresPredictionApiKeyRegistrationsListCall) Pages(ctx context.Context, f func(*GoogleCloudRecommendationengineV1beta1ListPredictionApiKeyRegistrationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

// method id "recommendationengine.projects.locations.catalogs.eventStores.userEvents.collect":

type ProjectsLocationsCatalogsEventStoresUserEventsCollectCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Collect: Writes a single user event from the browser. This uses a GET
// request to
// due to browser restriction of POST-ing to a 3rd party domain.
//
// This method is used only by the Recommendations AI JavaScript
// pixel.
// Users should not call this method directly.
func (r *ProjectsLocationsCatalogsEventStoresUserEventsService) Collect(parent string) *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall {
	c := &ProjectsLocationsCatalogsEventStoresUserEventsCollectCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Ets sets the optional parameter "ets": The event timestamp in
// milliseconds. This prevents browser caching of
// otherwise identical get requests. The name is abbreviated to reduce
// the
// payload bytes.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) Ets(ets int64) *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall {
	c.urlParams_.Set("ets", fmt.Sprint(ets))
	return c
}

// Uri sets the optional parameter "uri": The url including
// cgi-parameters but excluding the hash fragment. The URL
// must be truncated to 1.5K bytes to conservatively be under the 2K
// bytes.
// This is often more useful than the referer url, because many browsers
// only
// send the domain for 3rd party requests.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) Uri(uri string) *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall {
	c.urlParams_.Set("uri", uri)
	return c
}

// UserEvent sets the optional parameter "userEvent": Required. URL
// encoded UserEvent proto.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) UserEvent(userEvent string) *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall {
	c.urlParams_.Set("userEvent", userEvent)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/userEvents:collect")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.userEvents.collect" call.
// Exactly one of *GoogleApiHttpBody or error will be non-nil. Any
// non-2xx status code is an error. Response headers are in either
// *GoogleApiHttpBody.ServerResponse.Header or (if a response was
// returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsCollectCall) Do(opts ...googleapi.CallOption) (*GoogleApiHttpBody, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleApiHttpBody{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Writes a single user event from the browser. This uses a GET request to\ndue to browser restriction of POST-ing to a 3rd party domain.\n\nThis method is used only by the Recommendations AI JavaScript pixel.\nUsers should not call this method directly.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/userEvents:collect",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.userEvents.collect",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "ets": {
	//       "description": "Optional. The event timestamp in milliseconds. This prevents browser caching of\notherwise identical get requests. The name is abbreviated to reduce the\npayload bytes.",
	//       "format": "int64",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. The parent eventStore name, such as\n\"projects/1234/locations/global/catalogs/default_catalog/eventStores/default_event_store\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     },
	//     "uri": {
	//       "description": "Optional. The url including cgi-parameters but excluding the hash fragment. The URL\nmust be truncated to 1.5K bytes to conservatively be under the 2K bytes.\nThis is often more useful than the referer url, because many browsers only\nsend the domain for 3rd party requests.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "userEvent": {
	//       "description": "Required. URL encoded UserEvent proto.",
	//       "location": "query",
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/userEvents:collect",
	//   "response": {
	//     "$ref": "GoogleApiHttpBody"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.userEvents.import":

type ProjectsLocationsCatalogsEventStoresUserEventsImportCall struct {
	s                                                             *Service
	parent                                                        string
	googlecloudrecommendationenginev1beta1importusereventsrequest *GoogleCloudRecommendationengineV1beta1ImportUserEventsRequest
	urlParams_                                                    gensupport.URLParams
	ctx_                                                          context.Context
	header_                                                       http.Header
}

// Import: Bulk import of User events. Request processing might
// be
// synchronous. Events that already exist are skipped.
// Use this method for backfilling historical user
// events.
//
// Operation.response is of type ImportResponse. Note that it
// is
// possible for a subset of the items to be successfully
// inserted.
// Operation.metadata is of type ImportMetadata.
func (r *ProjectsLocationsCatalogsEventStoresUserEventsService) Import(parent string, googlecloudrecommendationenginev1beta1importusereventsrequest *GoogleCloudRecommendationengineV1beta1ImportUserEventsRequest) *ProjectsLocationsCatalogsEventStoresUserEventsImportCall {
	c := &ProjectsLocationsCatalogsEventStoresUserEventsImportCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecommendationenginev1beta1importusereventsrequest = googlecloudrecommendationenginev1beta1importusereventsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsImportCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresUserEventsImportCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsImportCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresUserEventsImportCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsImportCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresUserEventsImportCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1importusereventsrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/userEvents:import")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.userEvents.import" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsImportCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Bulk import of User events. Request processing might be\nsynchronous. Events that already exist are skipped.\nUse this method for backfilling historical user events.\n\nOperation.response is of type ImportResponse. Note that it is\npossible for a subset of the items to be successfully inserted.\nOperation.metadata is of type ImportMetadata.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/userEvents:import",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.userEvents.import",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. \"projects/1234/locations/global/catalogs/default_catalog/eventStores/default_event_store\"",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/userEvents:import",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1ImportUserEventsRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.userEvents.list":

type ProjectsLocationsCatalogsEventStoresUserEventsListCall struct {
	s            *Service
	parent       string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Gets a list of user events within a time range, with potential
// filtering.
// The method does not list unjoined user events.
//
// Unjoined user event definition: when a user event is ingested
// from
// Recommendations AI User Event APIs, the catalog item included in the
// user
// event is connected with the current catalog. If a catalog item of
// the
// ingested event is not in the current catalog, it could lead to
// degraded
// model quality. This is called an unjoined event.
func (r *ProjectsLocationsCatalogsEventStoresUserEventsService) List(parent string) *ProjectsLocationsCatalogsEventStoresUserEventsListCall {
	c := &ProjectsLocationsCatalogsEventStoresUserEventsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	return c
}

// Filter sets the optional parameter "filter": Filtering expression to
// specify restrictions over
// returned events. This is a sequence of terms, where each term applies
// some
// kind of a restriction to the returned user events. Use this
// expression to
// restrict results to a specific time range, or filter events by
// eventType.
//    eg: eventTime > "2012-04-23T18:25:43.511Z"
// eventsMissingCatalogItems
//    eventTime<"2012-04-23T18:25:43.511Z" eventType=search
//
//   We expect only 3 types of fields:
//
//    * eventTime: this can be specified a maximum of 2 times, once with
// a
//      less than operator and once with a greater than operator. The
//      eventTime restrict should result in one contiguous valid
// eventTime
//      range.
//
//    * eventType: only 1 eventType restriction can be specified.
//
//    * eventsMissingCatalogItems: specififying this will restrict
// results
//      to events for which catalog items were not found in the catalog.
// The
//      default behavior is to return only those events for which
// catalog
//      items were found.
//
//   Some examples of valid filters expressions:
//
//   * Example 1: eventTime > "2012-04-23T18:25:43.511Z"
//             eventTime < "2012-04-23T18:30:43.511Z"
//   * Example 2: eventTime > "2012-04-23T18:25:43.511Z"
//             eventType = detail-page-view
//   * Example 3: eventsMissingCatalogItems
//             eventType = search eventTime <
// "2018-04-23T18:30:43.511Z"
//   * Example 4: eventTime > "2012-04-23T18:25:43.511Z"
//   * Example 5: eventType = search
//   * Example 6: eventsMissingCatalogItems
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) Filter(filter string) *ProjectsLocationsCatalogsEventStoresUserEventsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": Maximum number of
// results to return per page. If zero, the
// service will choose a reasonable default.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) PageSize(pageSize int64) *ProjectsLocationsCatalogsEventStoresUserEventsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The previous
// ListUserEventsResponse.next_page_token.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) PageToken(pageToken string) *ProjectsLocationsCatalogsEventStoresUserEventsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresUserEventsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsEventStoresUserEventsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresUserEventsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/userEvents")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.userEvents.list" call.
// Exactly one of
// *GoogleCloudRecommendationengineV1beta1ListUserEventsResponse or
// error will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1ListUserEventsResponse.ServerRe
// sponse.Header or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1ListUserEventsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1ListUserEventsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Gets a list of user events within a time range, with potential filtering.\nThe method does not list unjoined user events.\n\nUnjoined user event definition: when a user event is ingested from\nRecommendations AI User Event APIs, the catalog item included in the user\nevent is connected with the current catalog. If a catalog item of the\ningested event is not in the current catalog, it could lead to degraded\nmodel quality. This is called an unjoined event.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/userEvents",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.userEvents.list",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "filter": {
	//       "description": "Optional. Filtering expression to specify restrictions over\nreturned events. This is a sequence of terms, where each term applies some\nkind of a restriction to the returned user events. Use this expression to\nrestrict results to a specific time range, or filter events by eventType.\n   eg: eventTime \u003e \"2012-04-23T18:25:43.511Z\" eventsMissingCatalogItems\n   eventTime\u003c\"2012-04-23T18:25:43.511Z\" eventType=search\n\n  We expect only 3 types of fields:\n\n   * eventTime: this can be specified a maximum of 2 times, once with a\n     less than operator and once with a greater than operator. The\n     eventTime restrict should result in one contiguous valid eventTime\n     range.\n\n   * eventType: only 1 eventType restriction can be specified.\n\n   * eventsMissingCatalogItems: specififying this will restrict results\n     to events for which catalog items were not found in the catalog. The\n     default behavior is to return only those events for which catalog\n     items were found.\n\n  Some examples of valid filters expressions:\n\n  * Example 1: eventTime \u003e \"2012-04-23T18:25:43.511Z\"\n            eventTime \u003c \"2012-04-23T18:30:43.511Z\"\n  * Example 2: eventTime \u003e \"2012-04-23T18:25:43.511Z\"\n            eventType = detail-page-view\n  * Example 3: eventsMissingCatalogItems\n            eventType = search eventTime \u003c \"2018-04-23T18:30:43.511Z\"\n  * Example 4: eventTime \u003e \"2012-04-23T18:25:43.511Z\"\n  * Example 5: eventType = search\n  * Example 6: eventsMissingCatalogItems",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "pageSize": {
	//       "description": "Optional. Maximum number of results to return per page. If zero, the\nservice will choose a reasonable default.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "Optional. The previous ListUserEventsResponse.next_page_token.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "parent": {
	//       "description": "Required. The parent eventStore resource name, such as\n\"projects/*/locations/*/catalogs/default_catalog/eventStores/default_event_store\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/userEvents",
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1ListUserEventsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsListCall) Pages(ctx context.Context, f func(*GoogleCloudRecommendationengineV1beta1ListUserEventsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}

// method id "recommendationengine.projects.locations.catalogs.eventStores.userEvents.purge":

type ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall struct {
	s                                                            *Service
	parent                                                       string
	googlecloudrecommendationenginev1beta1purgeusereventsrequest *GoogleCloudRecommendationengineV1beta1PurgeUserEventsRequest
	urlParams_                                                   gensupport.URLParams
	ctx_                                                         context.Context
	header_                                                      http.Header
}

// Purge: Deletes permanently all user events specified by the filter
// provided.
// Depending on the number of events specified by the filter, this
// operation
// could take hours or days to complete. To test a filter, use the
// list
// command first.
func (r *ProjectsLocationsCatalogsEventStoresUserEventsService) Purge(parent string, googlecloudrecommendationenginev1beta1purgeusereventsrequest *GoogleCloudRecommendationengineV1beta1PurgeUserEventsRequest) *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall {
	c := &ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecommendationenginev1beta1purgeusereventsrequest = googlecloudrecommendationenginev1beta1purgeusereventsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1purgeusereventsrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/userEvents:purge")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.userEvents.purge" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsPurgeCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Deletes permanently all user events specified by the filter provided.\nDepending on the number of events specified by the filter, this operation\ncould take hours or days to complete. To test a filter, use the list\ncommand first.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/userEvents:purge",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.userEvents.purge",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. The resource name of the event_store under which the events are\ncreated. The format is\n\"projects/${projectId}/locations/global/catalogs/${catalogId}/eventStores/${eventStoreId}\"",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/userEvents:purge",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1PurgeUserEventsRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.userEvents.rejoin":

type ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall struct {
	s                                                             *Service
	parent                                                        string
	googlecloudrecommendationenginev1beta1rejoinusereventsrequest *GoogleCloudRecommendationengineV1beta1RejoinUserEventsRequest
	urlParams_                                                    gensupport.URLParams
	ctx_                                                          context.Context
	header_                                                       http.Header
}

// Rejoin: Triggers a user event rejoin operation with latest catalog
// data. Events
// will not be annotated with detailed catalog information if catalog
// item is
// missing at the time the user event is ingested, and these events are
// stored
// as unjoined events with a limited usage on training and serving. This
// API
// can be used to trigger a 'join' operation on specified events with
// latest
// version of catalog items. It can also be used to correct events
// joined with
// wrong catalog items.
func (r *ProjectsLocationsCatalogsEventStoresUserEventsService) Rejoin(parent string, googlecloudrecommendationenginev1beta1rejoinusereventsrequest *GoogleCloudRecommendationengineV1beta1RejoinUserEventsRequest) *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall {
	c := &ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecommendationenginev1beta1rejoinusereventsrequest = googlecloudrecommendationenginev1beta1rejoinusereventsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1rejoinusereventsrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/userEvents:rejoin")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.userEvents.rejoin" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsRejoinCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Triggers a user event rejoin operation with latest catalog data. Events\nwill not be annotated with detailed catalog information if catalog item is\nmissing at the time the user event is ingested, and these events are stored\nas unjoined events with a limited usage on training and serving. This API\ncan be used to trigger a 'join' operation on specified events with latest\nversion of catalog items. It can also be used to correct events joined with\nwrong catalog items.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/userEvents:rejoin",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.userEvents.rejoin",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. Full resource name of user event, such as\n\"projects/*/locations/*/catalogs/default_catalog/eventStores/default_event_store\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/userEvents:rejoin",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1RejoinUserEventsRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.eventStores.userEvents.write":

type ProjectsLocationsCatalogsEventStoresUserEventsWriteCall struct {
	s                                               *Service
	parent                                          string
	googlecloudrecommendationenginev1beta1userevent *GoogleCloudRecommendationengineV1beta1UserEvent
	urlParams_                                      gensupport.URLParams
	ctx_                                            context.Context
	header_                                         http.Header
}

// Write: Writes a single user event.
func (r *ProjectsLocationsCatalogsEventStoresUserEventsService) Write(parent string, googlecloudrecommendationenginev1beta1userevent *GoogleCloudRecommendationengineV1beta1UserEvent) *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall {
	c := &ProjectsLocationsCatalogsEventStoresUserEventsWriteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googlecloudrecommendationenginev1beta1userevent = googlecloudrecommendationenginev1beta1userevent
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall) Context(ctx context.Context) *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googlecloudrecommendationenginev1beta1userevent)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+parent}/userEvents:write")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.eventStores.userEvents.write" call.
// Exactly one of *GoogleCloudRecommendationengineV1beta1UserEvent or
// error will be non-nil. Any non-2xx status code is an error. Response
// headers are in either
// *GoogleCloudRecommendationengineV1beta1UserEvent.ServerResponse.Header
//  or (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsCatalogsEventStoresUserEventsWriteCall) Do(opts ...googleapi.CallOption) (*GoogleCloudRecommendationengineV1beta1UserEvent, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudRecommendationengineV1beta1UserEvent{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Writes a single user event.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/eventStores/{eventStoresId}/userEvents:write",
	//   "httpMethod": "POST",
	//   "id": "recommendationengine.projects.locations.catalogs.eventStores.userEvents.write",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Required. The parent eventStore resource name, such as\n\"projects/1234/locations/global/catalogs/default_catalog/eventStores/default_event_store\".",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/eventStores/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+parent}/userEvents:write",
	//   "request": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1UserEvent"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudRecommendationengineV1beta1UserEvent"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.operations.get":

type ProjectsLocationsCatalogsOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation.  Clients can
// use this
// method to poll the operation result at intervals as recommended by
// the API
// service.
func (r *ProjectsLocationsCatalogsOperationsService) Get(name string) *ProjectsLocationsCatalogsOperationsGetCall {
	c := &ProjectsLocationsCatalogsOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsOperationsGetCall) Context(ctx context.Context) *ProjectsLocationsCatalogsOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.operations.get" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsOperationsGetCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Gets the latest state of a long-running operation.  Clients can use this\nmethod to poll the operation result at intervals as recommended by the API\nservice.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/operations/{operationsId}",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.operations.get",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "The name of the operation resource.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+/operations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}",
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "recommendationengine.projects.locations.catalogs.operations.list":

type ProjectsLocationsCatalogsOperationsListCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// List: Lists operations that match the specified filter in the
// request. If the
// server doesn't support this method, it returns
// `UNIMPLEMENTED`.
//
// NOTE: the `name` binding allows API services to override the
// binding
// to use different resource name schemes, such as `users/*/operations`.
// To
// override the binding, API services can add a binding such
// as
// "/v1/{name=users/*}/operations" to their service configuration.
// For backwards compatibility, the default name includes the
// operations
// collection id, however overriding users must ensure the name
// binding
// is the parent resource, without the operations collection id.
func (r *ProjectsLocationsCatalogsOperationsService) List(name string) *ProjectsLocationsCatalogsOperationsListCall {
	c := &ProjectsLocationsCatalogsOperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Filter sets the optional parameter "filter": The standard list
// filter.
func (c *ProjectsLocationsCatalogsOperationsListCall) Filter(filter string) *ProjectsLocationsCatalogsOperationsListCall {
	c.urlParams_.Set("filter", filter)
	return c
}

// PageSize sets the optional parameter "pageSize": The standard list
// page size.
func (c *ProjectsLocationsCatalogsOperationsListCall) PageSize(pageSize int64) *ProjectsLocationsCatalogsOperationsListCall {
	c.urlParams_.Set("pageSize", fmt.Sprint(pageSize))
	return c
}

// PageToken sets the optional parameter "pageToken": The standard list
// page token.
func (c *ProjectsLocationsCatalogsOperationsListCall) PageToken(pageToken string) *ProjectsLocationsCatalogsOperationsListCall {
	c.urlParams_.Set("pageToken", pageToken)
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsCatalogsOperationsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsCatalogsOperationsListCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsCatalogsOperationsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsCatalogsOperationsListCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsCatalogsOperationsListCall) Context(ctx context.Context) *ProjectsLocationsCatalogsOperationsListCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsCatalogsOperationsListCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsCatalogsOperationsListCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200801")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta1/{+name}/operations")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "recommendationengine.projects.locations.catalogs.operations.list" call.
// Exactly one of *GoogleLongrunningListOperationsResponse or error will
// be non-nil. Any non-2xx status code is an error. Response headers are
// in either
// *GoogleLongrunningListOperationsResponse.ServerResponse.Header or (if
// a response was returned at all) in error.(*googleapi.Error).Header.
// Use googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsCatalogsOperationsListCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningListOperationsResponse, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningListOperationsResponse{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Lists operations that match the specified filter in the request. If the\nserver doesn't support this method, it returns `UNIMPLEMENTED`.\n\nNOTE: the `name` binding allows API services to override the binding\nto use different resource name schemes, such as `users/*/operations`. To\noverride the binding, API services can add a binding such as\n`\"/v1/{name=users/*}/operations\"` to their service configuration.\nFor backwards compatibility, the default name includes the operations\ncollection id, however overriding users must ensure the name binding\nis the parent resource, without the operations collection id.",
	//   "flatPath": "v1beta1/projects/{projectsId}/locations/{locationsId}/catalogs/{catalogsId}/operations",
	//   "httpMethod": "GET",
	//   "id": "recommendationengine.projects.locations.catalogs.operations.list",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "filter": {
	//       "description": "The standard list filter.",
	//       "location": "query",
	//       "type": "string"
	//     },
	//     "name": {
	//       "description": "The name of the operation's parent resource.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/catalogs/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     },
	//     "pageSize": {
	//       "description": "The standard list page size.",
	//       "format": "int32",
	//       "location": "query",
	//       "type": "integer"
	//     },
	//     "pageToken": {
	//       "description": "The standard list page token.",
	//       "location": "query",
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta1/{+name}/operations",
	//   "response": {
	//     "$ref": "GoogleLongrunningListOperationsResponse"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// Pages invokes f for each page of results.
// A non-nil error returned from f will halt the iteration.
// The provided context supersedes any context provided to the Context method.
func (c *ProjectsLocationsCatalogsOperationsListCall) Pages(ctx context.Context, f func(*GoogleLongrunningListOperationsResponse) error) error {
	c.ctx_ = ctx
	defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
	for {
		x, err := c.Do()
		if err != nil {
			return err
		}
		if err := f(x); err != nil {
			return err
		}
		if x.NextPageToken == "" {
			return nil
		}
		c.PageToken(x.NextPageToken)
	}
}
