forked from IBM/platform-services-go-sdk
-
Notifications
You must be signed in to change notification settings - Fork 2
/
table_printer_utils.go
143 lines (120 loc) · 3.78 KB
/
table_printer_utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
* (C) Copyright IBM Corp. 2023.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package utils
import (
"reflect"
"strconv"
"strings"
)
// If there was a jmespath query against the data, this function will
// extract the final segment as it may need to be used as a column header.
// If no query was given, use a default of "values".
func GetLastQuerySegment(query string) string {
if query == "" {
return "values"
}
queryArr := strings.Split(query, ".")
return queryArr[len(queryArr)-1]
}
// Returns true if the value is a map that
// has exactly one property that is an array.
func HasExactlyOneArrayProperty(thing reflect.Value) bool {
// two potential paths here:
// 1. its a map
// 2. it is a type that can't have properties, so return false
numArrayProps := 0
if thing.Kind() == reflect.Map {
iter := thing.MapRange()
for iter.Next() {
// note that all values in the map are likely interfaces
// so we need to deref them
kind := DerefValue(iter.Value()).Kind()
if kind == reflect.Slice {
numArrayProps += 1
}
}
}
return numArrayProps == 1
}
// Return the dereferenced value if a pointer or interface,
// hand the value back if not.
func DerefValue(thing reflect.Value) reflect.Value {
if thing.Kind() == reflect.Interface {
// interface elements can be pointers
return DerefValue(thing.Elem())
} else if thing.Kind() == reflect.Ptr {
return thing.Elem()
} else {
return thing
}
}
// Takes the final value that is to be written to the table
// and formats it as a string if possible.
func GetStringValue(thing reflect.Value) string {
var result string
// don't bother with invalid values
if !thing.IsValid() {
return "-"
}
actualValue := thing.Interface()
switch thing.Kind() {
case reflect.String:
result = thing.String()
case reflect.Bool:
result = strconv.FormatBool(actualValue.(bool))
case reflect.Int64:
result = strconv.FormatInt(actualValue.(int64), 10)
case reflect.Float32:
// FormatFloat must take a float64 as its first value, so typecast is needed
result = strconv.FormatFloat(float64(actualValue.(float32)), 'g', -1, 32)
case reflect.Float64:
result = strconv.FormatFloat(actualValue.(float64), 'g', -1, 64)
case reflect.Map:
result = "<Nested Object>"
case reflect.Slice:
// print something if an array was returned but is hidden
// to indicate that there is data there
if thing.Len() > 0 {
result = "<Array>"
} else {
result = "-"
}
default:
// fmt.Println("Type not yet supported: " + thing.Kind().String())
result = "-"
}
return result
}
// for an array value, get the "Kind" of its individual elements
func GetArrayElementType(value reflect.Value) reflect.Kind {
arrayElementType := value.Type().Elem().Kind()
if arrayElementType == reflect.Interface {
// base the underlying types on the first value
firstInterface := DerefValue(value.Index(0))
arrayElementType = firstInterface.Kind()
}
return arrayElementType
}
// returns true if kind is Slice or Array
// returns false otherwise
func IsArrayType(kind reflect.Kind) bool {
return kind == reflect.Slice || kind == reflect.Array
}
// validates the data to ensure a table can be printed
// returns false if the table doesn't have sufficient data
func IsValidTableData(data *TableData) bool {
return data != nil && len(data.Headers) > 0
}