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) { 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 } parserFunc, exists := eiaapi.ParseFunctionsMap[fmt.Sprintf("Parse%sResponse", route)] if !exists { return nil, fmt.Errorf("parser func for %s not found", route) } parser := reflect.ValueOf(parserFunc) 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") } } return err }