github.com/CiscoM31/godata@v1.0.10/select_parser.go (about) 1 package godata 2 3 import ( 4 "context" 5 "errors" 6 "strings" 7 ) 8 9 type SelectItem struct { 10 Segments []*Token 11 } 12 13 func ParseSelectString(ctx context.Context, sel string) (*GoDataSelectQuery, error) { 14 return GlobalExpressionParser.ParseSelectString(ctx, sel) 15 } 16 17 func (p *ExpressionParser) ParseSelectString(ctx context.Context, sel string) (*GoDataSelectQuery, error) { 18 items := strings.Split(sel, ",") 19 20 result := []*SelectItem{} 21 22 for _, item := range items { 23 item = strings.TrimSpace(item) 24 25 cfg, hasComplianceConfig := ctx.Value(odataCompliance).(OdataComplianceConfig) 26 if !hasComplianceConfig { 27 // Strict ODATA compliance by default. 28 cfg = ComplianceStrict 29 } 30 31 if len(strings.TrimSpace(item)) == 0 && cfg&ComplianceIgnoreInvalidComma == 0 { 32 return nil, BadRequestError("Extra comma in $select.") 33 } 34 35 if _, err := p.tokenizer.Tokenize(ctx, item); err != nil { 36 switch e := err.(type) { 37 case *GoDataError: 38 return nil, &GoDataError{ 39 ResponseCode: e.ResponseCode, 40 Message: "Invalid $select value", 41 Cause: e, 42 } 43 default: 44 return nil, &GoDataError{ 45 ResponseCode: 500, 46 Message: "Invalid $select value", 47 Cause: e, 48 } 49 } 50 } else { 51 segments := []*Token{} 52 for _, val := range strings.Split(item, "/") { 53 segments = append(segments, &Token{Value: val}) 54 } 55 result = append(result, &SelectItem{segments}) 56 } 57 } 58 59 return &GoDataSelectQuery{result, sel}, nil 60 } 61 62 func SemanticizeSelectQuery(sel *GoDataSelectQuery, service *GoDataService, entity *GoDataEntityType) error { 63 if sel == nil { 64 return nil 65 } 66 67 newItems := []*SelectItem{} 68 69 // replace wildcards with every property of the entity 70 for _, item := range sel.SelectItems { 71 // TODO: allow multiple path segments 72 if len(item.Segments) > 1 { 73 return NotImplementedError("Multiple path segments in select clauses are not yet supported.") 74 } 75 76 if item.Segments[0].Value == "*" { 77 for _, prop := range service.PropertyLookup[entity] { 78 newItems = append(newItems, &SelectItem{[]*Token{{Value: prop.Name}}}) 79 } 80 } else { 81 newItems = append(newItems, item) 82 } 83 } 84 85 sel.SelectItems = newItems 86 87 for _, item := range sel.SelectItems { 88 if prop, ok := service.PropertyLookup[entity][item.Segments[0].Value]; ok { 89 item.Segments[0].SemanticType = SemanticTypeProperty 90 item.Segments[0].SemanticReference = prop 91 } else { 92 return errors.New("Entity " + entity.Name + " has no property " + item.Segments[0].Value) 93 } 94 } 95 96 return nil 97 }