224 lines
4.7 KiB
Go
224 lines
4.7 KiB
Go
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
|
|
}
|