Example #1
0
func (b *Backend) sort(info *db.ModelInfo, items *reflector.SliceReflector, field Expression, asc bool) apperror.Error {
	fieldName := ""
	if id, ok := field.(*IdentifierExpr); ok {
		fieldName = id.Identifier()
	} else if id, ok := field.(*ColFieldIdentifierExpr); ok {
		if id.Collection() != info.Collection() {
			return apperror.New("unsupported_sort", fmt.Sprint("The memory backend does not support sorting with joined collections"))
		}
		fieldName = id.Field()
	} else {
		return apperror.New("unsupported_sort", fmt.Sprintf("The memory backend does not support sorting with custom field expressions"))
	}

	attr := info.FindAttribute(fieldName)
	if attr == nil {
		return apperror.New("invalid_sort", fmt.Sprintf("Invalid sort for inexistant field %v", fieldName))
	}

	if err := items.SortByField(attr.Name(), asc); err != nil {
		return apperror.Wrap(err, "sort_error")
	}

	return nil
}
Example #2
0
func (b *Backend) filterItem(info *db.ModelInfo, item *reflector.Reflector, filter Expression) (bool, apperror.Error) {
	switch f := filter.(type) {
	case *AndExpr:
		// Check each filter.
		for _, e := range f.Expressions() {
			flag, err := b.filterItem(info, item, e)
			if err != nil {
				return false, err
			} else if !flag {
				// One filter does not match, so return false.
				return false, nil
			}
		}
		// All filters matched, we can return true.
		return true, nil

	case *OrExpr:
		// Check each filter.
		for _, e := range f.Expressions() {
			flag, err := b.filterItem(info, item, e)
			if err != nil {
				return false, err
			} else if flag {
				// One match is enough, so return true.
				return true, nil
			}
		}
		// No filters matched, so return false.
		return false, nil

	case *NotExpr:
		// Reverse nested filter.
		flag, err := b.filterItem(info, item, f.Not())
		if err != nil {
			return false, err
		} else {
			return !flag, nil
		}

	case FilterExpression:
		field := f.Field()

		fieldName := ""

		if id, ok := field.(*IdentifierExpr); ok {
			fieldName = id.Identifier()
		} else if id, ok := field.(*ColFieldIdentifierExpr); ok {
			if id.Collection() != info.Collection() {
				return false, apperror.New("unsupported_filter", fmt.Sprint("The memory backend does not support filtering with joined collections"))
			}
			fieldName = id.Field()
		} else {
			return false, apperror.New("unsupported_filter", fmt.Sprintf("The memory backend does not support filtering with custom field expressions"))
		}

		attr := info.FindAttribute(fieldName)
		if attr == nil {
			return false, apperror.New("invalid_filter", fmt.Sprintf("Invalid filter for inexistant field %v", fieldName))
		}

		operator := f.Operator()

		var clauseValue interface{}

		if valExpr, ok := f.Clause().(*ValueExpr); ok {
			clauseValue = valExpr.Value()
		} else {
			return false, apperror.New("unsupported_filter_clause", fmt.Sprintf("The memory backend does not support filtering with custom clause expressions"))
		}

		if info.StructName() != "" {
			b.Logger().Infof("filtering item with %v %v %v", fieldName, operator, clauseValue)
			s, err := item.Struct()
			if err != nil {
				return false, apperror.Wrap(err, "invalid_model_error")
			}
			flag, err := s.Field(attr.Name()).CompareTo(clauseValue, operator)
			if err != nil {
				return false, apperror.Wrap(err, "compare_error")
			}
			return flag, nil
		} else {
			// Assume a map.
			if !item.IsMap() {
				return false, apperror.New("filter_invalid_model", "Could not filter because model value is neither struct nor map.")
			}
			flag, err := reflector.R(item.Value().MapIndex(reflect.ValueOf(attr.BackendName()))).CompareTo(clauseValue, operator)
			if err != nil {
				return false, apperror.Wrap(err, "compare_error")
			}
			return flag, nil
		}

	default:
		b.Logger().Panicf("Unhandled filter expression: %v", reflect.TypeOf(filter))
	}

	return false, nil
}