1// Copyright 2019 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package discovery_v1
16
17import (
18	"encoding/json"
19	"errors"
20	"strings"
21
22	"github.com/googleapis/gnostic/compiler"
23)
24
25// APIsListServiceURL is the URL for the Google APIs Discovery Service
26const APIsListServiceURL = "https://www.googleapis.com/discovery/v1/apis"
27
28// A List represents the results of a call to the apis/list API.
29// https://developers.google.com/discovery/v1/reference/apis/list
30type List struct {
31	Kind             string `json:"kind"`
32	DiscoveryVersion string `json:"discoveryVersion"`
33	APIs             []*API `json:"items"`
34}
35
36func FetchListBytes() ([]byte, error) {
37	return compiler.FetchFile(APIsListServiceURL)
38}
39
40// Read the list of APIs from the apis/list service.
41func FetchList() (*List, error) {
42	bytes, err := FetchListBytes()
43	if err != nil {
44		return nil, err
45	}
46	return ParseList(bytes)
47}
48
49// ParseList unmarshals the bytes into a Document.
50func ParseList(bytes []byte) (*List, error) {
51	var listResponse List
52	err := json.Unmarshal(bytes, &listResponse)
53	return &listResponse, err
54}
55
56// An API represents an API description returned by the apis/list API.
57type API struct {
58	Kind              string            `json:"kind"`
59	ID                string            `json:"id"`
60	Name              string            `json:"name"`
61	Version           string            `json:"version"`
62	Title             string            `json:"title"`
63	Description       string            `json:"description"`
64	DiscoveryRestURL  string            `json:"discoveryRestUrl"`
65	DiscoveryLink     string            `json:"discoveryLink"`
66	Icons             map[string]string `json:"icons"`
67	DocumentationLink string            `json:"documentationLink"`
68	Labels            []string          `json:"labels"`
69	Preferred         bool              `json:"preferred"`
70}
71
72// APIWithNameAndVersion returns the API with a specified name and version.
73// If version is the empty string, the API name must be unique.
74func (a *List) APIWithNameAndVersion(name string, version string) (*API, error) {
75	var api *API                  // the API to return
76	versions := make([]string, 0) // the matching version names
77	// Scan the list for matching APIs and versions.
78	for _, item := range a.APIs {
79		if item.Name == name {
80			if version == "" || version == item.Version {
81				api = item
82				versions = append(versions, item.Version)
83			}
84		}
85	}
86	switch {
87	case len(versions) == 0:
88		return nil, errors.New(name + " was not found.")
89	case len(versions) > 1:
90		return nil, errors.New(name + " has multiple versions: " + strings.Join(versions, ", "))
91	default:
92		return api, nil
93	}
94}
95