github.com/CiscoM31/godata@v1.0.10/orderby_parser.go (about) 1 package godata 2 3 import ( 4 "context" 5 "strings" 6 ) 7 8 const ( 9 ASC = "asc" 10 DESC = "desc" 11 ) 12 13 type OrderByItem struct { 14 Field *Token // The raw value of the orderby field or expression. 15 Tree *GoDataExpression // The orderby expression parsed as a tree. 16 Order string // Ascending or descending order. 17 } 18 19 func ParseOrderByString(ctx context.Context, orderby string) (*GoDataOrderByQuery, error) { 20 return GlobalExpressionParser.ParseOrderByString(ctx, orderby) 21 } 22 23 // The value of the $orderby System Query option contains a comma-separated 24 // list of expressions whose primitive result values are used to sort the items. 25 // The service MUST order by the specified property in ascending order. 26 // 4.01 services MUST support case-insensitive values for asc and desc. 27 func (p *ExpressionParser) ParseOrderByString(ctx context.Context, orderby string) (*GoDataOrderByQuery, error) { 28 items := strings.Split(orderby, ",") 29 30 result := make([]*OrderByItem, 0) 31 32 for _, v := range items { 33 v = strings.TrimSpace(v) 34 35 cfg, hasComplianceConfig := ctx.Value(odataCompliance).(OdataComplianceConfig) 36 if !hasComplianceConfig { 37 // Strict ODATA compliance by default. 38 cfg = ComplianceStrict 39 } 40 41 if len(v) == 0 && cfg&ComplianceIgnoreInvalidComma == 0 { 42 return nil, BadRequestError("Extra comma in $orderby.") 43 } 44 45 var order string 46 vLower := strings.ToLower(v) 47 if strings.HasSuffix(vLower, " "+ASC) { 48 order = ASC 49 } else if strings.HasSuffix(vLower, " "+DESC) { 50 order = DESC 51 } 52 if order == "" { 53 order = ASC // default order 54 } else { 55 v = v[:len(v)-len(order)] 56 v = strings.TrimSpace(v) 57 } 58 59 if tree, err := p.ParseExpressionString(ctx, v); err != nil { 60 switch e := err.(type) { 61 case *GoDataError: 62 return nil, &GoDataError{ 63 ResponseCode: e.ResponseCode, 64 Message: "Invalid $orderby query option", 65 Cause: e, 66 } 67 default: 68 return nil, &GoDataError{ 69 ResponseCode: 500, 70 Message: "Invalid $orderby query option", 71 Cause: e, 72 } 73 } 74 } else { 75 result = append(result, &OrderByItem{ 76 Field: &Token{Value: unescapeUtfEncoding(v)}, 77 Tree: tree, 78 Order: order, 79 }) 80 81 } 82 } 83 84 return &GoDataOrderByQuery{result, orderby}, nil 85 } 86 87 func SemanticizeOrderByQuery(orderby *GoDataOrderByQuery, service *GoDataService, entity *GoDataEntityType) error { 88 if orderby == nil { 89 return nil 90 } 91 92 for _, item := range orderby.OrderByItems { 93 if prop, ok := service.PropertyLookup[entity][item.Field.Value]; ok { 94 item.Field.SemanticType = SemanticTypeProperty 95 item.Field.SemanticReference = prop 96 } else { 97 return BadRequestError("No property " + item.Field.Value + " for entity " + entity.Name) 98 } 99 } 100 101 return nil 102 }