package orm import ( "reflect" "time" ) type Document struct { // Created time. updated/added automatically. Created time.Time `bson:"createdAt" json:"createdAt"` // Modified time. updated/added automatically. Modified time.Time `bson:"updatedAt" json:"updatedAt"` model *Model exists bool `bson:"-"` self any `bson:"-"` } type IDocument interface { Append(field string, a ...interface{}) error Pull(field string, a ...any) error Swap(field string, i, j int) error Delete() error Remove() error Save() error setSelf(arg interface{}) getExists() bool setExists(n bool) setModified(Modified time.Time) setCreated(Modified time.Time) getModified() time.Time getCreated() time.Time serializeToStore() any getModel() *Model setModel(m Model) } func (d *Document) getCreated() time.Time { return d.Created } func (d *Document) setCreated(Created time.Time) { d.Created = Created } func (d *Document) getModified() time.Time { return d.Modified } func (d *Document) setModified(Modified time.Time) { d.Modified = Modified } func (d *Document) setSelf(arg interface{}) { d.self = arg } func (d *Document) getModel() *Model { return d.model } func (d *Document) setModel(m Model) { d.model = &m } func (d *Document) getExists() bool { return d.exists } func (d *Document) setExists(n bool) { d.exists = n } // Delete - deletes a model instance from the database func (d *Document) Delete() error { var err error val := valueOf(d.self) if val.Kind() == reflect.Slice { for i := 0; i < val.Len(); i++ { cur := val.Index(i) if err = doDelete(d, cur.Interface()); err != nil { return err } } return nil } else { return doDelete(d, d.self) } } // Remove - alias for Delete func (d *Document) Remove() error { return d.Delete() } // Save - updates this Model in the database, // or inserts it if it doesn't exist func (d *Document) Save() error { val := valueOf(d.self) if val.Kind() == reflect.Slice { for i := 0; i < val.Len(); i++ { cur := val.Index(i) if err := doSave(d.model.getColl(), !d.exists, cur.Interface()); err != nil { return err } } return nil } else { return doSave(d.model.getColl(), !d.exists, d.self) } } func (d *Document) serializeToStore() any { return serializeIDs((d).self) } // Append appends one or more items to `field`. // will error if this Model contains a reference // to multiple documents, or if `field` is not a // slice. func (d *Document) Append(field string, a ...interface{}) error { var d0 IDocument = d d0.getCreated() rv := reflect.ValueOf(d.self) selfRef := rv rt := reflect.TypeOf(d.self) if selfRef.Kind() == reflect.Pointer { selfRef = selfRef.Elem() rt = rt.Elem() } if err := checkStruct(selfRef); err != nil { return err } _, origV, err := getNested(field, selfRef) if err != nil { return err } origRef := makeSettable(*origV, (*origV).Interface()) fv := origRef if fv.Kind() == reflect.Pointer { fv = fv.Elem() } if fv.Kind() != reflect.Slice { return ErrNotASlice } for _, b := range a { val := reflect.ValueOf(incrementTagged(b)) fv.Set(reflect.Append(fv, val)) } return nil } // Pull - removes elements from the subdocument slice stored in `field`. func (d *Document) Pull(field string, a ...any) error { rv := reflect.ValueOf(d.self) selfRef := rv rt := reflect.TypeOf(d.self) if selfRef.Kind() == reflect.Pointer { selfRef = selfRef.Elem() rt = rt.Elem() } if err := checkStruct(selfRef); err != nil { return err } _, origV, err := getNested(field, selfRef) if err != nil { return err } origRef := makeSettable(*origV, (*origV).Interface()) fv := origRef if fv.Kind() == reflect.Pointer { fv = fv.Elem() } if fv.Kind() != reflect.Slice { return ErrNotASlice } outer: for _, b := range a { for i := 0; i < fv.Len(); i++ { if reflect.DeepEqual(b, fv.Index(i).Interface()) { fv.Set(pull(fv, i, fv.Index(i).Type())) break outer } } } return nil } // Swap - swaps the elements at indexes `i` and `j` in the // slice stored at `field` func (d *Document) Swap(field string, i, j int) error { rv := reflect.ValueOf(d.self) selfRef := rv rt := reflect.TypeOf(d.self) if selfRef.Kind() == reflect.Pointer { selfRef = selfRef.Elem() rt = rt.Elem() } if err := checkStruct(selfRef); err != nil { return err } _, origV, err := getNested(field, selfRef) if err != nil { return err } origRef := makeSettable(*origV, (*origV).Interface()) fv := origRef if fv.Kind() == reflect.Pointer { fv = fv.Elem() } if err = checkSlice(fv); err != nil { return err } if i >= fv.Len() || j >= fv.Len() { return ErrOutOfBounds } oi := fv.Index(i).Interface() oj := fv.Index(j).Interface() fv.Index(i).Set(reflect.ValueOf(oj)) fv.Index(j).Set(reflect.ValueOf(oi)) return nil }