1// Copyright 2012-2015 Oliver Eilhard. All rights reserved.
2// Use of this source code is governed by a MIT-license.
3// See http://olivere.mit-license.org/license.txt for details.
4
5package elastic
6
7import (
8	"encoding/json"
9	"fmt"
10	"log"
11	"net/url"
12	"strings"
13
14	"gopkg.in/olivere/elastic.v2/uritemplates"
15)
16
17var (
18	_ = fmt.Print
19	_ = log.Print
20	_ = strings.Index
21	_ = uritemplates.Expand
22	_ = url.Parse
23)
24
25// GetMappingService retrieves the mapping definitions for an index or
26// index/type. See at http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-mapping.html.
27type GetMappingService struct {
28	client            *Client
29	pretty            bool
30	index             []string
31	typ               []string
32	local             *bool
33	ignoreUnavailable *bool
34	allowNoIndices    *bool
35	expandWildcards   string
36}
37
38// NewGetMappingService creates a new GetMappingService.
39func NewGetMappingService(client *Client) *GetMappingService {
40	return &GetMappingService{
41		client: client,
42		index:  make([]string, 0),
43		typ:    make([]string, 0),
44	}
45}
46
47// Index is a list of index names.
48func (s *GetMappingService) Index(index ...string) *GetMappingService {
49	s.index = append(s.index, index...)
50	return s
51}
52
53// Type is a list of document types.
54func (s *GetMappingService) Type(typ ...string) *GetMappingService {
55	s.typ = append(s.typ, typ...)
56	return s
57}
58
59// AllowNoIndices indicates whether to ignore if a wildcard indices
60// expression resolves into no concrete indices.
61// This includes `_all` string or when no indices have been specified.
62func (s *GetMappingService) AllowNoIndices(allowNoIndices bool) *GetMappingService {
63	s.allowNoIndices = &allowNoIndices
64	return s
65}
66
67// ExpandWildcards indicates whether to expand wildcard expression to
68// concrete indices that are open, closed or both..
69func (s *GetMappingService) ExpandWildcards(expandWildcards string) *GetMappingService {
70	s.expandWildcards = expandWildcards
71	return s
72}
73
74// Local indicates whether to return local information, do not retrieve
75// the state from master node (default: false).
76func (s *GetMappingService) Local(local bool) *GetMappingService {
77	s.local = &local
78	return s
79}
80
81// IgnoreUnavailable indicates whether specified concrete indices should be
82// ignored when unavailable (missing or closed).
83func (s *GetMappingService) IgnoreUnavailable(ignoreUnavailable bool) *GetMappingService {
84	s.ignoreUnavailable = &ignoreUnavailable
85	return s
86}
87
88// Pretty indicates that the JSON response be indented and human readable.
89func (s *GetMappingService) Pretty(pretty bool) *GetMappingService {
90	s.pretty = pretty
91	return s
92}
93
94// buildURL builds the URL for the operation.
95func (s *GetMappingService) buildURL() (string, url.Values, error) {
96	var index, typ []string
97
98	if len(s.index) > 0 {
99		index = s.index
100	} else {
101		index = []string{"_all"}
102	}
103
104	if len(s.typ) > 0 {
105		typ = s.typ
106	} else {
107		typ = []string{"_all"}
108	}
109
110	// Build URL
111	path, err := uritemplates.Expand("/{index}/_mapping/{type}", map[string]string{
112		"index": strings.Join(index, ","),
113		"type":  strings.Join(typ, ","),
114	})
115	if err != nil {
116		return "", url.Values{}, err
117	}
118
119	// Add query string parameters
120	params := url.Values{}
121	if s.pretty {
122		params.Set("pretty", "1")
123	}
124	if s.ignoreUnavailable != nil {
125		params.Set("ignore_unavailable", fmt.Sprintf("%v", *s.ignoreUnavailable))
126	}
127	if s.allowNoIndices != nil {
128		params.Set("allow_no_indices", fmt.Sprintf("%v", *s.allowNoIndices))
129	}
130	if s.expandWildcards != "" {
131		params.Set("expand_wildcards", s.expandWildcards)
132	}
133	if s.local != nil {
134		params.Set("local", fmt.Sprintf("%v", *s.local))
135	}
136	return path, params, nil
137}
138
139// Validate checks if the operation is valid.
140func (s *GetMappingService) Validate() error {
141	return nil
142}
143
144// Do executes the operation. When successful, it returns a json.RawMessage.
145// If you specify an index, Elasticsearch returns HTTP status 404.
146// if you specify a type that does not exist, Elasticsearch returns
147// an empty map.
148func (s *GetMappingService) Do() (map[string]interface{}, error) {
149	// Check pre-conditions
150	if err := s.Validate(); err != nil {
151		return nil, err
152	}
153
154	// Get URL for request
155	path, params, err := s.buildURL()
156	if err != nil {
157		return nil, err
158	}
159
160	// Get HTTP response
161	res, err := s.client.PerformRequest("GET", path, params, nil)
162	if err != nil {
163		return nil, err
164	}
165
166	// Return operation response
167	var ret map[string]interface{}
168	if err := json.Unmarshal(res.Body, &ret); err != nil {
169		return nil, err
170	}
171	return ret, nil
172}
173