Commit 7f7a8871 authored by Muhammad Umair Khan's avatar Muhammad Umair Khan
Browse files

fix issue in query parameter filtering to MEC 021 Mobility Service GET request

parent 14faeca8
Loading
Loading
Loading
Loading
+126 −207
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import (
	"net/http"
	"net/url"
	"os"
	"regexp"
	"sort"
	"strconv"
	"strings"
@@ -1488,6 +1489,7 @@ func appMobilityServiceByIdDELETE(w http.ResponseWriter, r *http.Request) {
}

func appMobilityServiceGET(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	// Validate query parameters
@@ -1502,16 +1504,17 @@ func appMobilityServiceGET(w http.ResponseWriter, r *http.Request) {
	}

	// Parse query parameters
	filters := q.Get("filter")
	allFields := q.Get("all_fields")
	urlFilter := q.Get("filter")
	// allFields := q.Get("all_fields")
	// field := q["fields"]
	// excludeFields := q["exclude_fields"]
	// excludeDefault := q.Get("exclude_default")

	if urlFilter != "" {
		fmt.Printf("filter: %s", urlFilter)
	}
	regInfoList := &RegisterationInfoList{
		Filters: &FilterParameters{
			filter:     filters,
			all_fields: allFields,
			filter: urlFilter,
		},
		Registrations: make([]RegistrationInfo, 0),
	}
@@ -1549,7 +1552,6 @@ func populateRegInfoList(key string, jsonEntry string, response interface{}) err
	// Retrieve registration info from DB
	var regInfo RegistrationInfo
	err := json.Unmarshal([]byte(jsonEntry), &regInfo)
	println("keysss", key)
	if err != nil {
		return err
	}
@@ -1557,18 +1559,25 @@ func populateRegInfoList(key string, jsonEntry string, response interface{}) err
	// Filter services
	if data.Filters != nil {

		// Filter Paramter
		if data.Filters.filter != "" {

			filterField := data.Filters.filter
			fmt.Printf("Filter Field: %s", filterField)
			// Split filterField into operator, attribute, and value
			filterField = strings.Trim(filterField, "()")
			filterParts := strings.SplitN(filterField, ",", 3)
			if len(filterParts) != 3 {
				return nil
			}
			operator := filterParts[0]
			attribute := filterParts[1]
			value := filterParts[2]
			operator, attribute, value, _ := parseFilter(string(filterField))

			fmt.Printf("operator: %s", operator)
			fmt.Printf("attribute: %s", attribute)
			fmt.Printf("value: %s", value)
			// filterField = strings.Trim(filterField, "()")
			// filterParts := strings.SplitN(filterField, ",", 3)
			// if len(filterParts) != 3 {
			// 	return nil
			// }
			// operator := filterParts[0]
			// attribute := filterParts[1]
			// value := filterParts[2]

			// Apply filters based on attribute
			switch attribute {
@@ -1577,17 +1586,17 @@ func populateRegInfoList(key string, jsonEntry string, response interface{}) err
					return nil
				}

			case "serviceConsumerId.appInstanceId":
			case "serviceConsumerId/appInstanceId":
				if !applyStringFilter(operator, regInfo.ServiceConsumerId.AppInstanceId, value) {
					return nil
				}

			case "serviceConsumerId.mepId":
			case "serviceConsumerId/mepId":
				if !applyStringFilter(operator, regInfo.ServiceConsumerId.MepId, value) {
					return nil
				}

			case "deviceInformation.associateId":
			case "deviceInformation/associateId":
				matched := false
				for _, deviceInfo := range regInfo.DeviceInformation {
					if applyStringFilter(operator, deviceInfo.AssociateId.Value, value) {
@@ -1599,17 +1608,17 @@ func populateRegInfoList(key string, jsonEntry string, response interface{}) err
					return nil
				}

			// case "deviceInformation.contextTransferState":
			// 	matched := false
			// 	for _, deviceInfo := range regInfo.DeviceInformation {
			// 		if applyEnumFilter(operator, string(deviceInfo.ContextTransferState.val), value) {
			// 			matched = true
			// 			break
			// 		}
			// 	}
			// 	if !matched {
			// 		return fmt.Errorf("filter mismatch: deviceInformation.contextTransferState")
			// 	}
			case "deviceInformation/contextTransferState":
				matched := false
				for _, deviceInfo := range regInfo.DeviceInformation {
					if applyEnumFilter(operator, string(*deviceInfo.ContextTransferState), value) {
						matched = true
						break
					}
				}
				if !matched {
					return nil
				}

			case "expiryTime":
				expiryTime, err := strconv.ParseUint(value, 10, 32)
@@ -1631,185 +1640,6 @@ func populateRegInfoList(key string, jsonEntry string, response interface{}) err
	return nil
}

// Helper functions for applying filters
func applyStringFilter(operator, fieldValue, filterValue string) bool {
	switch operator {
	case "eq":
		return fieldValue == filterValue
	case "neq":
		return fieldValue != filterValue
	case "cont":
		return strings.Contains(fieldValue, filterValue)
	case "ncont":
		return !strings.Contains(fieldValue, filterValue)
	case "in":
		values := strings.Split(filterValue, ",")
		for _, v := range values {
			if fieldValue == v {
				return true
			}
		}
		return false
	case "nin":
		values := strings.Split(filterValue, ",")
		for _, v := range values {
			if fieldValue == v {
				return false
			}
		}
		return true
	case "gt":
		return fieldValue > filterValue
	case "gte":
		return fieldValue >= filterValue
	case "lt":
		return fieldValue < filterValue
	case "lte":
		return fieldValue <= filterValue
	default:
		return false
	}
}

func applyEnumFilter(operator, fieldValue, filterValue string) bool {
	return applyStringFilter(operator, fieldValue, filterValue)
}

func applyNumericFilter(operator string, fieldValue, filterValue uint32) bool {
	switch operator {
	case "eq":
		return fieldValue == filterValue
	case "neq":
		return fieldValue != filterValue
	case "gt":
		return fieldValue > filterValue
	case "gte":
		return fieldValue >= filterValue
	case "lt":
		return fieldValue < filterValue
	case "lte":
		return fieldValue <= filterValue
	default:
		return false
	}
}

// Original
// func populateRegInfoList(key string, jsonEntry string, response interface{}) error {
// 	data := response.(*RegisterationInfoList)
// 	if data == nil {
// 		return errors.New("response not defined")
// 	}

// 	// Retrieve registration info from DB
// 	var regInfo RegistrationInfo
// 	err := json.Unmarshal([]byte(jsonEntry), &regInfo)
// 	println("keysss", key)
// 	if err == nil {
// 		return err
// 	}

// 	// Filter services
// 	if data.Filters != nil {

// 		if data.Filters.filter != "" {
// 			filterField := data.Filters.filter
// 			if regInfo.AppMobilityServiceId == "" || (filterField != regInfo.AppMobilityServiceId) {
// 				return nil
// 			}
// 		}

// 	}

// 	data.Registrations = append(data.Registrations, regInfo)
// 	return nil
// }

// filterRegistrationInfo applies filtering based on the provided filters.
// func filterRegistrationInfo(regInfoList []RegistrationInfo, filters []string) []RegistrationInfo {
// 	var filteredList []RegistrationInfo

// 	for _, regInfo := range regInfoList {
// 		match := true

// 		// Iterate over filters to apply them one by one
// 		for _, filter := range filters {
// 			filterParts := strings.Split(filter, ":")
// 			if len(filterParts) != 2 {
// 				// Invalid filter format (e.g., "key:value")
// 				continue
// 			}
// 			key := filterParts[0]
// 			value := filterParts[1]

// 			// Apply filter based on key-value pairs
// 			switch key {
// 			case "appMobilityServiceId":
// 				if regInfo.AppMobilityServiceId != value {
// 					match = false
// 				}
// 			case "appInstanceId":
// 				if regInfo.ServiceConsumerId.AppInstanceId != value {
// 					match = false
// 				}
// 			case "mepId":
// 				if regInfo.ServiceConsumerId.MepId != value {
// 					match = false
// 				}
// 			case "associateId":
// 				// Check if any device has the associateId value
// 				found := false
// 				for _, device := range regInfo.DeviceInformation {
// 					if device.AssociateId == value {
// 						found = true
// 						break
// 					}
// 				}
// 				if !found {
// 					match = false
// 				}
// 			case "expiryTime":
// 				expiryTime, err := strconv.Atoi(value)
// 				if err != nil || regInfo.ExpiryTime != uint32(expiryTime) {
// 					match = false
// 				}
// 			default:
// 				// If filter key is not recognized, skip it
// 				continue
// 			}

// 			// If any filter condition doesn't match, we stop checking further
// 			if !match {
// 				break
// 			}
// 		}

// 		// If all filters matched, add to the result list
// 		if match {
// 			filteredList = append(filteredList, regInfo)
// 		}
// 	}

// 	return filteredList
// }

// func populateRegInfoList(key string, jsonEntry string, response interface{}) error {
// 	regInfoList := response.(*[]RegistrationInfo)
// 	if regInfoList == nil {
// 		return errors.New("Response not defined")
// 	}

// 	// Retrieve registration info from DB
// 	var regInfo RegistrationInfo
// 	err := json.Unmarshal([]byte(jsonEntry), &regInfo)
// 	if err != nil {
// 		return err
// 	}

// 	*regInfoList = append(*regInfoList, regInfo)
// 	return nil
// }

func cleanUp() {
	log.Info("Terminate all")

@@ -2668,3 +2498,92 @@ func errHandlerProblemDetails(w http.ResponseWriter, error string, code int) {
	w.WriteHeader(code)
	fmt.Fprint(w, jsonResponse)
}

func parseFilter(filterField string) (string, string, string, error) {
	// Regular expression to match the filter format
	re := regexp.MustCompile(`^(eq|neq|gt|lt|gte|lte|in|nin|cont|ncont),([a-zA-Z0-9/]+),([^,]+)(?:,([^,]+))?$`)

	// Trim any surrounding parentheses
	filterField = strings.Trim(filterField, "()")

	// Match the filterField against the regular expression
	matches := re.FindStringSubmatch(filterField)
	if len(matches) < 3 {
		return "", "", "", nil
	}

	// Extract the operator, attribute, and value(s)
	operator := matches[1]
	attribute := matches[2]
	value := matches[3]

	// If there's a second value (for operators like "in" or "nin"), handle it
	if len(matches) > 4 && matches[4] != "" {
		value += "," + matches[4]
	}

	return operator, attribute, value, nil
}

// Helper functions for applying filters
func applyStringFilter(operator, fieldValue, filterValue string) bool {
	switch operator {
	case "eq":
		return fieldValue == filterValue
	case "neq":
		return fieldValue != filterValue
	case "cont":
		return strings.Contains(fieldValue, filterValue)
	case "ncont":
		return !strings.Contains(fieldValue, filterValue)
	case "in":
		values := strings.Split(filterValue, ",")
		for _, v := range values {
			if fieldValue == v {
				return true
			}
		}
		return false
	case "nin":
		values := strings.Split(filterValue, ",")
		for _, v := range values {
			if fieldValue == v {
				return false
			}
		}
		return true
	case "gt":
		return fieldValue > filterValue
	case "gte":
		return fieldValue >= filterValue
	case "lt":
		return fieldValue < filterValue
	case "lte":
		return fieldValue <= filterValue
	default:
		return false
	}
}

func applyEnumFilter(operator, fieldValue, filterValue string) bool {
	return applyStringFilter(operator, fieldValue, filterValue)
}

func applyNumericFilter(operator string, fieldValue, filterValue uint32) bool {
	switch operator {
	// case "eq":
	// 	return fieldValue == filterValue
	// case "neq":
	// 	return fieldValue != filterValue
	case "gt":
		return fieldValue > filterValue
	case "gte":
		return fieldValue >= filterValue
	case "lt":
		return fieldValue < filterValue
	case "lte":
		return fieldValue <= filterValue
	default:
		return false
	}
}