123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- package worker
- /*
- the worker middleware is for doing some part of tranformtion on the business object side.
- Here you will find functions for validating the model validating and storage and retrieval in an storage technologie indipendent way.
- */
- import (
- "errors"
- "fmt"
- "reflect"
- "sync"
- "time"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/config"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/dao"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/internal"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/logging"
- "wkla.no-ip.biz/gogs/Willie/MsgService/MessageService/model"
- )
- //ErrMissingID the id of the model is mandatory and not availble
- var ErrMissingID = errors.New("Missing _id")
- //ErrBackendNotFound backend with that name was not found
- var ErrBackendNotFound = errors.New("Missing backend")
- //ErrBackendModelNotFound backend model with that name was not found
- var ErrBackendModelNotFound = errors.New("Missing backend model")
- type ErrValidationError struct {
- message string
- }
- func (p ErrValidationError) Error() string {
- return p.message
- }
- var modelCount = make(map[string]int)
- var modelCountMutex = &sync.Mutex{}
- func GetModelCount() map[string]int {
- internaleCountMap := make(map[string]int)
- modelCountMutex.Lock()
- for k, v := range modelCount {
- internaleCountMap[k] = v
- }
- modelCountMutex.Unlock()
- return internaleCountMap
- }
- func IncModelCounter(name string, count int) {
- modelCountMutex.Lock()
- modelCount[name] = modelCount[name] + count
- modelCountMutex.Unlock()
- }
- var log logging.ServiceLogger
- //CheckRoute checking if the route inforamtion are ok
- func CheckRoute(route model.Route) error {
- if !config.Get().AllowAnonymousBackend {
- backend, ok := model.BackendList.Get(route.Backend)
- if !ok {
- log.Alertf("backend not found: %s", route.Backend)
- return ErrBackendNotFound
- }
- _, ok = backend.GetModel(route.Model)
- if !ok {
- log.Alertf("backend model not found: %s.%s", route.Backend, route.Model)
- return ErrBackendModelNotFound
- }
- }
- return nil
- }
- //Validate validates the model against the definition, and convert attributes, if there is something to convert (like dateTime attributes)
- func Validate(route model.Route, data model.JSONMap) (model.JSONMap, error) {
- // return false, dao.ErrNotImplemented
- err := CheckRoute(route)
- if err != nil {
- return nil, err
- }
- modelDefinition, ok := model.BackendList.GetModel(route)
- if !ok || !config.Get().AllowAnonymousBackend {
- return nil, ErrBackendModelNotFound
- }
- log.Info(modelDefinition.Name)
- // check fieldtypes, eventually convert
- //TODO check field values
- for key, value := range data {
- field, ok := modelDefinition.GetField(key)
- if !ok {
- continue
- }
- if field.Mandatory {
- if isEmpty(value) {
- return nil, ErrValidationError{
- message: fmt.Sprintf("mandatory field \"%s\" is empty", key),
- }
- }
- }
- if field.Collection {
- if !isEmpty(value) {
- //TODO check and convert every array entry
- if reflect.TypeOf(value).Kind() != reflect.Slice {
- return nil, ErrValidationError{
- message: fmt.Sprintf("collection field \"%s\" is not a collection", key),
- }
- }
- }
- }
- if field.Type == model.FieldTypeBool {
- switch v := value.(type) {
- case float64:
- data[key] = v > 0
- case int:
- data[key] = v > 0
- case bool:
- data[key] = v
- }
- }
- if field.Type == model.FieldTypeTime {
- switch v := value.(type) {
- case string:
- layout := "2006-01-02T15:04:05.000Z07:00"
- time, err := time.Parse(layout, v)
- if err != nil {
- return nil, ErrValidationError{
- message: fmt.Sprintf("wrong time format: key: \"%s\", err: %v", key, err),
- }
- }
- data[key] = time
- case float64:
- data[key] = time.Unix(0, int64(v)*int64(time.Millisecond))
- }
- }
- }
- //check mandatory fields
- for _, field := range modelDefinition.Fields {
- if field.Mandatory {
- if isEmpty(data[field.Name]) {
- return nil, ErrValidationError{
- message: fmt.Sprintf("mandatory field \"%s\" is empty", field.Name),
- }
- }
- }
- }
- return data, nil
- }
- func isEmpty(value interface{}) bool {
- if value == nil {
- return true
- }
- switch v := value.(type) {
- case string:
- return v == ""
- }
- return false
- }
- //Store create a new model
- func Store(route model.Route, data model.JSONMap) (model.JSONMap, error) {
- err := CheckRoute(route)
- if err != nil {
- return nil, err
- }
- // adding system attributes
- data[internal.AttributeOwner] = route.Username
- data[internal.AttributeCreated] = time.Now()
- data[internal.AttributeModified] = time.Now()
- modelid, err := dao.GetStorage().CreateModel(route, data)
- if err != nil {
- return nil, err
- }
- IncModelCounter(route.GetRouteName(), 1)
- route.Identity = modelid
- modelData, err := Get(route)
- if err != nil {
- return nil, err
- }
- return modelData, nil
- }
- //StoreMany create a bunch of new model
- func StoreMany(route model.Route, datas []model.JSONMap) ([]string, error) {
- err := CheckRoute(route)
- if err != nil {
- return nil, err
- }
- now := time.Now()
- for _, data := range datas {
- // adding system attributes
- data[internal.AttributeOwner] = route.Username
- data[internal.AttributeCreated] = now
- data[internal.AttributeModified] = now
- }
- modelids, err := dao.GetStorage().CreateModels(route, datas)
- if err != nil {
- return nil, err
- }
- return modelids, nil
- }
- //Get getting one model
- func Get(route model.Route) (model.JSONMap, error) {
- err := CheckRoute(route)
- if err != nil {
- return nil, err
- }
- model, err := dao.GetStorage().GetModel(route)
- if err != nil {
- return nil, err
- }
- return model, nil
- }
- //Update update an existing model
- func Update(route model.Route, data model.JSONMap) (model.JSONMap, error) {
- err := CheckRoute(route)
- if err != nil {
- return nil, err
- }
- if route.Identity == "" {
- return nil, ErrMissingID
- }
- dataModel, err := dao.GetStorage().GetModel(route)
- if err != nil {
- return nil, err
- }
- // adding system attributes
- data[internal.AttributeID] = route.Identity
- data[internal.AttributeOwner] = route.Username
- data[internal.AttributeCreated] = dataModel[internal.AttributeCreated]
- data[internal.AttributeModified] = time.Now()
- modelData, err := dao.GetStorage().UpdateModel(route, data)
- if err != nil {
- fmt.Printf("%v\n", err)
- return nil, err
- }
- return modelData, nil
- }
- //Delete delete an existing model
- func Delete(route model.Route, deleteRef bool) error {
- err := CheckRoute(route)
- if err != nil {
- return err
- }
- if route.Identity == "" {
- return ErrMissingID
- }
- data, err := dao.GetStorage().GetModel(route)
- if err != nil {
- return err
- }
- beModel, ok := model.BackendList.Get(route.Backend)
- if ok {
- fmt.Printf("getting backend %s\n", beModel.Backendname)
- if beModel.IsValidDatamodel(route.Model, data) && deleteRef {
- files, err := beModel.GetReferencedFiles(route.Model, data)
- if err != nil {
- return err
- }
- for _, fileID := range files {
- err = dao.GetStorage().DeleteFile(route.Backend, fileID)
- if err != nil {
- return err
- }
- }
- }
- }
- err = dao.GetStorage().DeleteModel(route)
- if err != nil {
- return err
- }
- return nil
- }
- //Query query for existing models
- func Query(route model.Route, query string, offset int, limit int) (int, []model.JSONMap, error) {
- err := CheckRoute(route)
- if err != nil {
- return 0, nil, err
- }
- n, dataModels, err := dao.GetStorage().QueryModel(route, query, offset, limit)
- if err != nil {
- return 0, nil, err
- }
- return n, dataModels, nil
- }
- //GetCount query for existing models
- func GetCount(route model.Route) (int, error) {
- err := CheckRoute(route)
- if err != nil {
- return 0, err
- }
- n, err := dao.GetStorage().CountModel(route)
- if err != nil {
- return 0, err
- }
- return n, nil
- }
|