eia-api-go/cmd/eia-client/internal/util/util_reflect.go

131 lines
3.1 KiB
Go
Raw Normal View History

2024-11-26 15:54:55 +00:00
package util
import (
"context"
"errors"
"fmt"
"net/http"
"reflect"
"strconv"
"time"
"github.com/spf13/cobra"
eiaapi "gitea.libretechconsulting.com/50W/eia-api-go/api"
)
func GetFacets(cmd *cobra.Command, route string) (*eiaapi.FacetOptionList, error) {
2024-11-26 15:54:55 +00:00
client, err := Client(cmd)
if err != nil {
return nil, err
}
// Get the reflect.Value of the target object
targetValue := reflect.ValueOf(client)
// Get the method by name
method := targetValue.MethodByName(route)
if !method.IsValid() {
return nil, fmt.Errorf("method %q not found", route)
}
// Create a slice of reflect.Value for the method's arguments
methodType := method.Type()
args := make([]reflect.Value, 0, methodType.NumIn())
// Populate arguments with zero values for their respective types
for i := 0; i < methodType.NumIn(); i++ {
argType := methodType.In(i)
// Don't supply request editor Fn args
if methodType.IsVariadic() && i == methodType.NumIn()-1 {
continue
}
if argType == reflect.TypeOf((*context.Context)(nil)).Elem() {
args = append(args, reflect.ValueOf(cmd.Context()))
continue
}
// Default to last year for Route1
if argType == reflect.TypeOf(eiaapi.Route1("1999")) {
lastYear := time.Now().AddDate(-1, 0, 0).Year()
args = append(args, reflect.ValueOf(eiaapi.Route1(strconv.Itoa(lastYear))))
continue
}
// Zero value of other stuff
args = append(args, reflect.Zero(argType))
}
results := method.Call(args)
if len(results) != 2 {
return nil, errors.New("unexpected response from get facet call")
}
var resp *http.Response
var ok bool
if resp, ok = results[0].Interface().(*http.Response); !ok {
return nil, errors.New("no or invalid response received from call")
}
if err := checkCallErr(results[1]); err != nil {
return nil, err
2024-11-26 15:54:55 +00:00
}
parserFunc, exists := eiaapi.ParseFunctionsMap[fmt.Sprintf("Parse%sResponse", route)]
if !exists {
return nil, fmt.Errorf("parser func for %s not found", route)
2024-11-26 15:54:55 +00:00
}
parser := reflect.ValueOf(parserFunc)
2024-11-26 15:54:55 +00:00
if !parser.IsValid() {
return nil, errors.New("unable to find parser for facet response")
}
results = parser.Call([]reflect.Value{reflect.ValueOf(resp)})
if len(results) != 2 {
return nil, errors.New("unexpected response while parsing facet response")
}
if err := checkCallErr(results[1]); err != nil {
return nil, err
}
result := results[0]
if result.Kind() == reflect.Ptr {
result = result.Elem()
}
if result.Kind() != reflect.Struct {
return nil, fmt.Errorf("unexpected parse result kind %s", result.Kind().String())
}
field := result.FieldByName("JSON200")
if !field.IsValid() {
return nil, errors.New("invalid facet data field in response")
}
facetOptions, ok := field.Interface().(*eiaapi.FacetOptionListContainer)
if !ok {
return nil, errors.New("response does not contain facet options")
}
if facetOptions == nil {
return nil, errors.New("no facet options found for facet request")
}
return facetOptions.Response, nil
}
func checkCallErr(val reflect.Value) error {
var err error
var ok bool
if val.IsValid() && !val.IsNil() {
if err, ok = val.Interface().(error); !ok {
return errors.New("unexpected call response")
}
}
2024-11-26 15:54:55 +00:00
return err
2024-11-26 15:54:55 +00:00
}