1package objx
2
3/*
4   MSI (map[string]interface{} and []map[string]interface{})
5*/
6
7// MSI gets the value as a map[string]interface{}, returns the optionalDefault
8// value or a system default object if the value is the wrong type.
9func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} {
10	if s, ok := v.data.(map[string]interface{}); ok {
11		return s
12	}
13	if s, ok := v.data.(Map); ok {
14		return map[string]interface{}(s)
15	}
16	if len(optionalDefault) == 1 {
17		return optionalDefault[0]
18	}
19	return nil
20}
21
22// MustMSI gets the value as a map[string]interface{}.
23//
24// Panics if the object is not a map[string]interface{}.
25func (v *Value) MustMSI() map[string]interface{} {
26	if s, ok := v.data.(Map); ok {
27		return map[string]interface{}(s)
28	}
29	return v.data.(map[string]interface{})
30}
31
32// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault
33// value or nil if the value is not a []map[string]interface{}.
34func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} {
35	if s, ok := v.data.([]map[string]interface{}); ok {
36		return s
37	}
38
39	s := v.ObjxMapSlice()
40	if s == nil {
41		if len(optionalDefault) == 1 {
42			return optionalDefault[0]
43		}
44		return nil
45	}
46
47	result := make([]map[string]interface{}, len(s))
48	for i := range s {
49		result[i] = s[i].Value().MSI()
50	}
51	return result
52}
53
54// MustMSISlice gets the value as a []map[string]interface{}.
55//
56// Panics if the object is not a []map[string]interface{}.
57func (v *Value) MustMSISlice() []map[string]interface{} {
58	if s := v.MSISlice(); s != nil {
59		return s
60	}
61
62	return v.data.([]map[string]interface{})
63}
64
65// IsMSI gets whether the object contained is a map[string]interface{} or not.
66func (v *Value) IsMSI() bool {
67	_, ok := v.data.(map[string]interface{})
68	if !ok {
69		_, ok = v.data.(Map)
70	}
71	return ok
72}
73
74// IsMSISlice gets whether the object contained is a []map[string]interface{} or not.
75func (v *Value) IsMSISlice() bool {
76	_, ok := v.data.([]map[string]interface{})
77	if !ok {
78		_, ok = v.data.([]Map)
79		if !ok {
80			s, ok := v.data.([]interface{})
81			if ok {
82				for i := range s {
83					switch s[i].(type) {
84					case Map:
85					case map[string]interface{}:
86					default:
87						return false
88					}
89				}
90				return true
91			}
92		}
93	}
94	return ok
95}
96
97// EachMSI calls the specified callback for each object
98// in the []map[string]interface{}.
99//
100// Panics if the object is the wrong type.
101func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value {
102	for index, val := range v.MustMSISlice() {
103		carryon := callback(index, val)
104		if !carryon {
105			break
106		}
107	}
108	return v
109}
110
111// WhereMSI uses the specified decider function to select items
112// from the []map[string]interface{}.  The object contained in the result will contain
113// only the selected items.
114func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value {
115	var selected []map[string]interface{}
116	v.EachMSI(func(index int, val map[string]interface{}) bool {
117		shouldSelect := decider(index, val)
118		if !shouldSelect {
119			selected = append(selected, val)
120		}
121		return true
122	})
123	return &Value{data: selected}
124}
125
126// GroupMSI uses the specified grouper function to group the items
127// keyed by the return of the grouper.  The object contained in the
128// result will contain a map[string][]map[string]interface{}.
129func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value {
130	groups := make(map[string][]map[string]interface{})
131	v.EachMSI(func(index int, val map[string]interface{}) bool {
132		group := grouper(index, val)
133		if _, ok := groups[group]; !ok {
134			groups[group] = make([]map[string]interface{}, 0)
135		}
136		groups[group] = append(groups[group], val)
137		return true
138	})
139	return &Value{data: groups}
140}
141
142// ReplaceMSI uses the specified function to replace each map[string]interface{}s
143// by iterating each item.  The data in the returned result will be a
144// []map[string]interface{} containing the replaced items.
145func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value {
146	arr := v.MustMSISlice()
147	replaced := make([]map[string]interface{}, len(arr))
148	v.EachMSI(func(index int, val map[string]interface{}) bool {
149		replaced[index] = replacer(index, val)
150		return true
151	})
152	return &Value{data: replaced}
153}
154
155// CollectMSI uses the specified collector function to collect a value
156// for each of the map[string]interface{}s in the slice.  The data returned will be a
157// []interface{}.
158func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value {
159	arr := v.MustMSISlice()
160	collected := make([]interface{}, len(arr))
161	v.EachMSI(func(index int, val map[string]interface{}) bool {
162		collected[index] = collector(index, val)
163		return true
164	})
165	return &Value{data: collected}
166}
167
168/*
169   ObjxMap ((Map) and [](Map))
170*/
171
172// ObjxMap gets the value as a (Map), returns the optionalDefault
173// value or a system default object if the value is the wrong type.
174func (v *Value) ObjxMap(optionalDefault ...(Map)) Map {
175	if s, ok := v.data.((Map)); ok {
176		return s
177	}
178	if s, ok := v.data.(map[string]interface{}); ok {
179		return s
180	}
181	if len(optionalDefault) == 1 {
182		return optionalDefault[0]
183	}
184	return New(nil)
185}
186
187// MustObjxMap gets the value as a (Map).
188//
189// Panics if the object is not a (Map).
190func (v *Value) MustObjxMap() Map {
191	if s, ok := v.data.(map[string]interface{}); ok {
192		return s
193	}
194	return v.data.((Map))
195}
196
197// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault
198// value or nil if the value is not a [](Map).
199func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) {
200	if s, ok := v.data.([]Map); ok {
201		return s
202	}
203
204	if s, ok := v.data.([]map[string]interface{}); ok {
205		result := make([]Map, len(s))
206		for i := range s {
207			result[i] = s[i]
208		}
209		return result
210	}
211
212	s, ok := v.data.([]interface{})
213	if !ok {
214		if len(optionalDefault) == 1 {
215			return optionalDefault[0]
216		}
217		return nil
218	}
219
220	result := make([]Map, len(s))
221	for i := range s {
222		switch s[i].(type) {
223		case Map:
224			result[i] = s[i].(Map)
225		case map[string]interface{}:
226			result[i] = New(s[i])
227		default:
228			return nil
229		}
230	}
231	return result
232}
233
234// MustObjxMapSlice gets the value as a [](Map).
235//
236// Panics if the object is not a [](Map).
237func (v *Value) MustObjxMapSlice() [](Map) {
238	if s := v.ObjxMapSlice(); s != nil {
239		return s
240	}
241	return v.data.([](Map))
242}
243
244// IsObjxMap gets whether the object contained is a (Map) or not.
245func (v *Value) IsObjxMap() bool {
246	_, ok := v.data.((Map))
247	if !ok {
248		_, ok = v.data.(map[string]interface{})
249	}
250	return ok
251}
252
253// IsObjxMapSlice gets whether the object contained is a [](Map) or not.
254func (v *Value) IsObjxMapSlice() bool {
255	_, ok := v.data.([](Map))
256	if !ok {
257		_, ok = v.data.([]map[string]interface{})
258		if !ok {
259			s, ok := v.data.([]interface{})
260			if ok {
261				for i := range s {
262					switch s[i].(type) {
263					case Map:
264					case map[string]interface{}:
265					default:
266						return false
267					}
268				}
269				return true
270			}
271		}
272	}
273
274	return ok
275}
276
277// EachObjxMap calls the specified callback for each object
278// in the [](Map).
279//
280// Panics if the object is the wrong type.
281func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value {
282	for index, val := range v.MustObjxMapSlice() {
283		carryon := callback(index, val)
284		if !carryon {
285			break
286		}
287	}
288	return v
289}
290
291// WhereObjxMap uses the specified decider function to select items
292// from the [](Map).  The object contained in the result will contain
293// only the selected items.
294func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value {
295	var selected [](Map)
296	v.EachObjxMap(func(index int, val Map) bool {
297		shouldSelect := decider(index, val)
298		if !shouldSelect {
299			selected = append(selected, val)
300		}
301		return true
302	})
303	return &Value{data: selected}
304}
305
306// GroupObjxMap uses the specified grouper function to group the items
307// keyed by the return of the grouper.  The object contained in the
308// result will contain a map[string][](Map).
309func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value {
310	groups := make(map[string][](Map))
311	v.EachObjxMap(func(index int, val Map) bool {
312		group := grouper(index, val)
313		if _, ok := groups[group]; !ok {
314			groups[group] = make([](Map), 0)
315		}
316		groups[group] = append(groups[group], val)
317		return true
318	})
319	return &Value{data: groups}
320}
321
322// ReplaceObjxMap uses the specified function to replace each (Map)s
323// by iterating each item.  The data in the returned result will be a
324// [](Map) containing the replaced items.
325func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value {
326	arr := v.MustObjxMapSlice()
327	replaced := make([](Map), len(arr))
328	v.EachObjxMap(func(index int, val Map) bool {
329		replaced[index] = replacer(index, val)
330		return true
331	})
332	return &Value{data: replaced}
333}
334
335// CollectObjxMap uses the specified collector function to collect a value
336// for each of the (Map)s in the slice.  The data returned will be a
337// []interface{}.
338func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value {
339	arr := v.MustObjxMapSlice()
340	collected := make([]interface{}, len(arr))
341	v.EachObjxMap(func(index int, val Map) bool {
342		collected[index] = collector(index, val)
343		return true
344	})
345	return &Value{data: collected}
346}
347