mirror of
https://github.com/luscis/openlan.git
synced 2025-10-14 12:54:48 +08:00
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
|
|
"github.com/ovn-org/libovsdb/mapper"
|
|
"github.com/ovn-org/libovsdb/ovsdb"
|
|
)
|
|
|
|
// A DatabaseModel represents libovsdb's metadata about the database.
|
|
// It's the result of combining the client's ClientDBModel and the server's Schema
|
|
type DatabaseModel struct {
|
|
client ClientDBModel
|
|
Schema ovsdb.DatabaseSchema
|
|
Mapper mapper.Mapper
|
|
metadata map[reflect.Type]mapper.Metadata
|
|
}
|
|
|
|
// NewDatabaseModel returns a new DatabaseModel
|
|
func NewDatabaseModel(schema ovsdb.DatabaseSchema, client ClientDBModel) (DatabaseModel, []error) {
|
|
dbModel := &DatabaseModel{
|
|
Schema: schema,
|
|
client: client,
|
|
}
|
|
errs := client.validate(schema)
|
|
if len(errs) > 0 {
|
|
return DatabaseModel{}, errs
|
|
}
|
|
dbModel.Mapper = mapper.NewMapper(schema)
|
|
var metadata map[reflect.Type]mapper.Metadata
|
|
metadata, errs = generateModelInfo(schema, client.types)
|
|
if len(errs) > 0 {
|
|
return DatabaseModel{}, errs
|
|
}
|
|
dbModel.metadata = metadata
|
|
return *dbModel, nil
|
|
}
|
|
|
|
// NewPartialDatabaseModel returns a DatabaseModel what does not have a schema yet
|
|
func NewPartialDatabaseModel(client ClientDBModel) DatabaseModel {
|
|
return DatabaseModel{
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
// Valid returns whether the DatabaseModel is fully functional
|
|
func (db DatabaseModel) Valid() bool {
|
|
return !reflect.DeepEqual(db.Schema, ovsdb.DatabaseSchema{})
|
|
}
|
|
|
|
// Client returns the DatabaseModel's client dbModel
|
|
func (db DatabaseModel) Client() ClientDBModel {
|
|
return db.client
|
|
}
|
|
|
|
// NewModel returns a new instance of a model from a specific string
|
|
func (db DatabaseModel) NewModel(table string) (Model, error) {
|
|
mtype, ok := db.client.types[table]
|
|
if !ok {
|
|
return nil, fmt.Errorf("table %s not found in database model", string(table))
|
|
}
|
|
model := reflect.New(mtype.Elem())
|
|
return model.Interface().(Model), nil
|
|
}
|
|
|
|
// Types returns the DatabaseModel Types
|
|
// the DatabaseModel types is a map of reflect.Types indexed by string
|
|
// The reflect.Type is a pointer to a struct that contains 'ovs' tags
|
|
// as described above. Such pointer to struct also implements the Model interface
|
|
func (db DatabaseModel) Types() map[string]reflect.Type {
|
|
return db.client.types
|
|
}
|
|
|
|
// FindTable returns the string associated with a reflect.Type or ""
|
|
func (db DatabaseModel) FindTable(mType reflect.Type) string {
|
|
for table, tType := range db.client.types {
|
|
if tType == mType {
|
|
return table
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// generateModelMetadata creates metadata objects from all models included in the
|
|
// database and caches them for future re-use
|
|
func generateModelInfo(dbSchema ovsdb.DatabaseSchema, modelTypes map[string]reflect.Type) (map[reflect.Type]mapper.Metadata, []error) {
|
|
errors := []error{}
|
|
metadata := make(map[reflect.Type]mapper.Metadata, len(modelTypes))
|
|
for tableName, tType := range modelTypes {
|
|
tableSchema := dbSchema.Table(tableName)
|
|
if tableSchema == nil {
|
|
errors = append(errors, fmt.Errorf("database Model contains model for table %s which is not present in schema", tableName))
|
|
continue
|
|
}
|
|
|
|
obj := reflect.New(tType.Elem()).Interface().(Model)
|
|
info, err := mapper.NewInfo(tableName, tableSchema, obj)
|
|
if err != nil {
|
|
errors = append(errors, err)
|
|
continue
|
|
}
|
|
metadata[tType] = info.Metadata
|
|
}
|
|
return metadata, errors
|
|
}
|
|
|
|
// NewModelInfo returns a mapper.Info object based on a provided model
|
|
func (db DatabaseModel) NewModelInfo(obj interface{}) (*mapper.Info, error) {
|
|
meta, ok := db.metadata[reflect.TypeOf(obj)]
|
|
if !ok {
|
|
return nil, ovsdb.NewErrWrongType("NewModelInfo", "type that is part of the DatabaseModel", obj)
|
|
}
|
|
return &mapper.Info{
|
|
Obj: obj,
|
|
Metadata: meta,
|
|
}, nil
|
|
}
|