github.com/angryronald/go-kit@v0.0.0-20240505173814-ff2bd9c79dbf/generic/repository/generic.utils.go (about)

     1  package repository
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  	"unicode"
     9  
    10  	"github.com/google/uuid"
    11  )
    12  
    13  func IsValidOperations(conditionalOperations []ConditionalOperation, relationalOperations []RelationalOperation, params map[string]interface{}) bool {
    14  	if (len(params) == len(conditionalOperations) && len(conditionalOperations)-len(relationalOperations) == 1) || (len(conditionalOperations) == 0 && len(relationalOperations) == 0 && len(params) == 0) {
    15  		return true
    16  	}
    17  
    18  	return false
    19  }
    20  
    21  //	func ToSnakeCase(s string) string {
    22  //		var result []string
    23  //		for i, r := range s {
    24  //			if i > 0 && unicode.IsUpper(r) {
    25  //				result = append(result, "_")
    26  //			}
    27  //			result = append(result, strings.ToLower(string(r)))
    28  //		}
    29  //		return strings.Join(result, "")
    30  //	}
    31  func ToSnakeCase(s string) string {
    32  	var result strings.Builder
    33  
    34  	for i, r := range s {
    35  		if i > 0 && unicode.IsUpper(r) {
    36  			nextIsLower := i < len(s)-1 && unicode.IsLower(rune(s[i+1]))
    37  			if nextIsLower {
    38  				result.WriteByte('_')
    39  			}
    40  		}
    41  		result.WriteRune(unicode.ToLower(r))
    42  	}
    43  	return result.String()
    44  }
    45  
    46  func GetTableName(model interface{}) string {
    47  	// typeName := reflect.TypeOf(model).Elem().Name()
    48  	t := reflect.TypeOf(model)
    49  	for t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
    50  		t = t.Elem()
    51  	}
    52  	typeName := t.Name()
    53  	return ToSnakeCase(typeName) + "s"
    54  }
    55  
    56  func IsMapStringInterface(obj interface{}) bool {
    57  	// Use reflection to check the type of the object.
    58  	objType := reflect.TypeOf(obj)
    59  	return objType.Kind() == reflect.Map && objType.Key().Kind() == reflect.String && objType.Elem().Kind() == reflect.Interface
    60  }
    61  
    62  // GetStructPropertyAsString retrieves the value of a specific property from a struct
    63  // and converts it to a string. If the property is of type uuid.UUID, it's converted to a string.
    64  func GetStructPropertyAsString(inputStruct interface{}, propertyName string) (string, error) {
    65  	if IsMapStringInterface(inputStruct) {
    66  		result, ok := inputStruct.(map[string]interface{})
    67  		if !ok {
    68  			return "", fmt.Errorf("input is not a map[string]interface{}")
    69  		}
    70  		return fmt.Sprint(result[propertyName]), nil
    71  	}
    72  	valueOfData := reflect.ValueOf(inputStruct)
    73  
    74  	// Ensure obj is a pointer to a struct
    75  	if valueOfData.Kind() != reflect.Ptr || valueOfData.Elem().Kind() != reflect.Struct {
    76  		return "", errors.New("object must be a pointer to a struct")
    77  	}
    78  
    79  	valueOfData = valueOfData.Elem()
    80  
    81  	t := valueOfData.Type()
    82  
    83  	for i := 0; i < t.NumField(); i++ {
    84  		field := t.Field(i)
    85  		fieldValue := valueOfData.Field(i)
    86  
    87  		if strings.ToUpper(field.Name) == propertyName {
    88  			// break
    89  			if fieldValue.Type() == reflect.TypeOf(uuid.UUID{}) {
    90  				uuidValue, ok := fieldValue.Interface().(uuid.UUID)
    91  				if !ok {
    92  					return "", fmt.Errorf("failed to convert field '%s' to UUID", propertyName)
    93  				}
    94  				return uuidValue.String(), nil
    95  			} else {
    96  				return fmt.Sprintf("%v", fieldValue.Interface()), nil
    97  			}
    98  		}
    99  	}
   100  
   101  	return "", fmt.Errorf("field '%s' does not exist in the struct", propertyName)
   102  }
   103  
   104  // CopyObject creates a new object with the same field values as the source object.
   105  func CopyObject(src interface{}) (interface{}, error) {
   106  	// Ensure src is a pointer to a struct.
   107  	srcValue := reflect.ValueOf(src)
   108  
   109  	if srcValue.Kind() != reflect.Ptr {
   110  		return nil, fmt.Errorf("src must be a pointer")
   111  	}
   112  
   113  	srcElem := srcValue.Elem()
   114  
   115  	if srcElem.Kind() != reflect.Struct {
   116  		return nil, fmt.Errorf("src must point to a struct")
   117  	}
   118  
   119  	// Create a new object of the same type as src.
   120  	dest := reflect.New(srcElem.Type()).Interface()
   121  
   122  	// Get the value of the destination object.
   123  	destValue := reflect.ValueOf(dest).Elem()
   124  
   125  	// Copy the fields from src to dest.
   126  	for i := 0; i < srcElem.NumField(); i++ {
   127  		srcField := srcElem.Field(i)
   128  		destField := destValue.Field(i)
   129  
   130  		// Check if the field is exported (starts with an uppercase letter).
   131  		if srcField.CanInterface() {
   132  			// Set the value of the destination field to the value of the source field.
   133  			destField.Set(srcField)
   134  		}
   135  	}
   136  
   137  	return dest, nil
   138  }
   139  
   140  func CopySliceOfPointers(slice interface{}) (interface{}, error) {
   141  	// Ensure that the input is a slice.
   142  	sliceValue := reflect.ValueOf(slice)
   143  	if sliceValue.Kind() != reflect.Slice {
   144  		return nil, fmt.Errorf("input must be a slice")
   145  	}
   146  
   147  	// Create a new slice of the same type.
   148  	newSlice := reflect.MakeSlice(sliceValue.Type(), sliceValue.Len(), sliceValue.Cap())
   149  
   150  	// Copy each element from the source slice to the new slice.
   151  	for i := 0; i < sliceValue.Len(); i++ {
   152  		srcElement := sliceValue.Index(i)
   153  		if srcElement.Kind() != reflect.Ptr || srcElement.Elem().Kind() != reflect.Struct {
   154  			return nil, fmt.Errorf("element at index %d is not a struct pointer", i)
   155  		}
   156  
   157  		// Create a new instance of the struct type and copy the field values.
   158  		destElement := reflect.New(srcElement.Elem().Type()).Elem()
   159  		destElement.Set(srcElement.Elem())
   160  
   161  		newSlice.Index(i).Set(destElement.Addr())
   162  	}
   163  
   164  	return newSlice.Interface(), nil
   165  }
   166  
   167  func CopySliceOfPointersWithIdentitySeparated(sourceSlice interface{}, slice []interface{}) (interface{}, error) {
   168  	// Ensure that the input is a slice.
   169  	sliceValue := reflect.ValueOf(sourceSlice)
   170  	if sliceValue.Kind() != reflect.Slice {
   171  		return nil, fmt.Errorf("input must be a slice")
   172  	}
   173  
   174  	// Create a new slice of the same type.
   175  	newSlice := reflect.MakeSlice(sliceValue.Type(), 0, 0)
   176  
   177  	for _, s := range slice {
   178  		sWithIdentity := reflect.ValueOf(s)
   179  		newSlice = reflect.Append(newSlice, sWithIdentity)
   180  	}
   181  
   182  	return newSlice.Interface(), nil
   183  }
   184  
   185  func AreAllNumbers(arr []interface{}) bool {
   186  	for _, elem := range arr {
   187  		switch elem.(type) {
   188  		case int, int8, int16, int32, int64,
   189  			uint, uint8, uint16, uint32, uint64,
   190  			float32, float64:
   191  			// Do nothing, element is a number
   192  			break
   193  		default:
   194  			return false // Element is not a number
   195  		}
   196  	}
   197  	return true // All elements are numbers
   198  }
   199  
   200  func StringJoin(arr []interface{}, encapsulation string) string {
   201  	result := ""
   202  	for _, elem := range arr {
   203  		result = fmt.Sprintf(`%s%s%v%s,`, result, encapsulation, elem, encapsulation)
   204  	}
   205  	return result[:len(result)-1]
   206  }
   207  
   208  func UpdatePropertyValue(obj interface{}, propertyName string, newValue interface{}) error {
   209  	// Make sure the input is a pointer to a struct.
   210  	val := reflect.ValueOf(obj)
   211  	if val.Kind() != reflect.Ptr || val.Elem().Kind() != reflect.Struct {
   212  		return fmt.Errorf("input must be a pointer to a struct")
   213  	}
   214  
   215  	// Get the value of the ID field.
   216  	idField := val.Elem().FieldByName(propertyName)
   217  	if !idField.IsValid() {
   218  		return ErrPropertyNotFound
   219  	}
   220  
   221  	// Check if the newID has the same type as the ID field.
   222  	if idField.Type() != reflect.TypeOf(newValue) {
   223  		return ErrPropertyTypeNotMatch
   224  	}
   225  
   226  	// Update the ID field with the new value.
   227  	idField.Set(reflect.ValueOf(newValue))
   228  
   229  	return nil
   230  }
   231  
   232  func AreAllUUIDs(arr []interface{}) bool {
   233  	for _, elem := range arr {
   234  		switch elem.(type) {
   235  		case uuid.UUID:
   236  			// Do nothing, element is a number
   237  			break
   238  		default:
   239  			return false // Element is not a number
   240  		}
   241  	}
   242  	return true
   243  }