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  }