From ffba973163a9194e646ae6b7d845621e840bcad3 Mon Sep 17 00:00:00 2001 From: pransh62390 <63577123+pransh62390@users.noreply.github.com> Date: Tue, 21 Jan 2025 21:26:37 +0530 Subject: [PATCH] added model for subcategory Signed-off-by: pransh62390 --- models/v1beta1/category/category.go | 7 +- models/v1beta1/subCategory/sub_category.go | 10 ++ .../subCategory/sub_category_helper.go | 92 +++++++++++++++++++ 3 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 models/v1beta1/subCategory/sub_category.go create mode 100644 models/v1beta1/subCategory/sub_category_helper.go diff --git a/models/v1beta1/category/category.go b/models/v1beta1/category/category.go index 197cf51668..ad119bca01 100644 --- a/models/v1beta1/category/category.go +++ b/models/v1beta1/category/category.go @@ -6,7 +6,8 @@ package category import "github.com/gofrs/uuid" type CategoryDefinition struct { - Id uuid.UUID `json:"-"` - Name string `json:"name" gorm:"name"` - Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" gorm:"type:bytes;serializer:json"` + Id uuid.UUID `json:"-"` + Name string `json:"name" gorm:"name"` + SubCategories []SubCategoryDefinition `gorm:"foreignKey:CategoryID"` + Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" gorm:"type:bytes;serializer:json"` } diff --git a/models/v1beta1/subCategory/sub_category.go b/models/v1beta1/subCategory/sub_category.go new file mode 100644 index 0000000000..f711e06842 --- /dev/null +++ b/models/v1beta1/subCategory/sub_category.go @@ -0,0 +1,10 @@ +package subCategory + +import "github.com/gofrs/uuid" + +type SubCategoryDefinition struct { + Id uuid.UUID `json:"-"` + Name string `json:"name" gorm:"name"` + CategoryID uuid.UUID `json:"category_id" gorm:"category_id"` + Metadata map[string]interface{} `json:"metadata,omitempty" yaml:"metadata,omitempty" gorm:"type:bytes;serializer:json"` +} diff --git a/models/v1beta1/subCategory/sub_category_helper.go b/models/v1beta1/subCategory/sub_category_helper.go new file mode 100644 index 0000000000..2546376e33 --- /dev/null +++ b/models/v1beta1/subCategory/sub_category_helper.go @@ -0,0 +1,92 @@ +// The file implements the Entity interface on the SubCategoryDefinition struct. +package subCategory + +import ( + "crypto/md5" + "encoding/hex" + "encoding/json" + "fmt" + "sync" + + "github.com/gofrs/uuid" + "github.com/layer5io/meshkit/database" + "github.com/layer5io/meshkit/models/meshmodel/entity" + "gorm.io/gorm" +) + +var subCategoryCreationLock sync.Mutex + +// GenerateID generates a unique ID for a sub-category based on its name and category ID. +func (cat *SubCategoryDefinition) GenerateID() (uuid.UUID, error) { + categoryIdentifier := struct { + Name string + CategoryID uuid.UUID + }{ + Name: cat.Name, + CategoryID: cat.CategoryID, + } + + byt, err := json.Marshal(categoryIdentifier) + if err != nil { + return uuid.UUID{}, err + } + + hash := md5.Sum(byt) + return uuid.FromString(hex.EncodeToString(hash[:])) +} + +// Create adds a new sub-category to the database. +func (cat *SubCategoryDefinition) Create(db *database.Handler) (uuid.UUID, error) { + if cat.Name == "" { + return uuid.UUID{}, fmt.Errorf("sub-category name cannot be empty") + } + + if cat.CategoryID == uuid.Nil { + return uuid.UUID{}, fmt.Errorf("category ID is required") + } + + // Generate ID for the sub-category. + catID, err := cat.GenerateID() + if err != nil { + return uuid.UUID{}, err + } + + // Ensure thread safety. + subCategoryCreationLock.Lock() + defer subCategoryCreationLock.Unlock() + + var existingSubCategory SubCategoryDefinition + err = db.First(&existingSubCategory, "id = ?", catID).Error + if err != nil && err != gorm.ErrRecordNotFound { + return uuid.UUID{}, err + } + + // If no record exists, create a new one. + if err == gorm.ErrRecordNotFound { + cat.Id = catID + err = db.Create(&cat).Error + if err != nil { + return uuid.UUID{}, err + } + return cat.Id, nil + } + + // If record exists, return the existing ID. + return existingSubCategory.Id, nil +} + +// LinkCategory creates a relationship between a category and its sub-categories. +func LinkCategory(db *database.Handler, category *CategoryDefinition, subCategories []SubCategoryDefinition) error { + if category.Id == uuid.Nil { + return fmt.Errorf("category ID is required") + } + + for i := range subCategories { + subCategories[i].CategoryID = category.Id + if _, err := subCategories[i].Create(db); err != nil { + return fmt.Errorf("failed to create sub-category: %w", err) + } + } + + return nil +}