From 7c08f60262de2d6497ef330131b14897f20a4d50 Mon Sep 17 00:00:00 2001 From: Uwe Krueger Date: Sat, 5 Oct 2024 12:32:34 +0200 Subject: [PATCH] descriptive + flagsetscheme --- api/credentials/cpi/repotypes.go | 6 +- api/credentials/internal/repotypes.go | 10 +- api/ocm/cpi/accspeccpi/accesstypes.go | 6 +- .../labels/routingslip/internal/entrytypes.go | 8 +- .../labels/routingslip/spi/support.go | 6 +- api/ocm/extensions/pubsub/interface.go | 14 +- api/ocm/internal/accesstypes.go | 6 +- .../flagsets/flagsetscheme/common.go | 19 ++ .../{types_options.go => options.go} | 20 ++- .../flagsets/flagsetscheme/scheme.go | 62 ++++--- .../cobrautils/flagsets/flagsetscheme/type.go | 41 +++++ .../flagsets/flagsetscheme/types.go | 62 ------- .../flagsets/flagsetscheme/versioned.go | 43 +++++ api/utils/runtime/descriptivetype/common.go | 27 +++ api/utils/runtime/descriptivetype/options.go | 25 +-- api/utils/runtime/descriptivetype/scheme.go | 132 ++++++++++++++ api/utils/runtime/descriptivetype/type.go | 165 ++---------------- .../runtime/descriptivetype/versionedtype.go | 71 ++++++++ .../ocmcmds/common/addhdlrs/comp/elements.go | 12 +- 19 files changed, 449 insertions(+), 286 deletions(-) create mode 100644 api/utils/cobrautils/flagsets/flagsetscheme/common.go rename api/utils/cobrautils/flagsets/flagsetscheme/{types_options.go => options.go} (69%) create mode 100644 api/utils/cobrautils/flagsets/flagsetscheme/type.go delete mode 100644 api/utils/cobrautils/flagsets/flagsetscheme/types.go create mode 100644 api/utils/cobrautils/flagsets/flagsetscheme/versioned.go create mode 100644 api/utils/runtime/descriptivetype/common.go create mode 100644 api/utils/runtime/descriptivetype/scheme.go create mode 100644 api/utils/runtime/descriptivetype/versionedtype.go diff --git a/api/credentials/cpi/repotypes.go b/api/credentials/cpi/repotypes.go index 673998c36..e76e10fcf 100644 --- a/api/credentials/cpi/repotypes.go +++ b/api/credentials/cpi/repotypes.go @@ -25,15 +25,15 @@ func RegisterRepositoryTypeVersions(s RepositoryTypeVersionScheme) { //////////////////////////////////////////////////////////////////////////////// func NewRepositoryType[I RepositorySpec](name string, opts ...RepositoryOption) RepositoryType { - return descriptivetype.NewTypedObjectTypeObject(runtime.NewVersionedTypedObjectType[RepositorySpec, I](name), opts...) + return descriptivetype.NewVersionedTypedObjectTypeObject(runtime.NewVersionedTypedObjectType[RepositorySpec, I](name), opts...) } func NewRepositoryTypeByConverter[I RepositorySpec, V runtime.TypedObject](name string, converter runtime.Converter[I, V], opts ...RepositoryOption) RepositoryType { - return descriptivetype.NewTypedObjectTypeObject(runtime.NewVersionedTypedObjectTypeByConverter[RepositorySpec, I](name, converter), opts...) + return descriptivetype.NewVersionedTypedObjectTypeObject(runtime.NewVersionedTypedObjectTypeByConverter[RepositorySpec, I](name, converter), opts...) } func NewRepositoryTypeByFormatVersion(name string, fmt runtime.FormatVersion[RepositorySpec], opts ...RepositoryOption) RepositoryType { - return descriptivetype.NewTypedObjectTypeObject(runtime.NewVersionedTypedObjectTypeByFormatVersion[RepositorySpec](name, fmt), opts...) + return descriptivetype.NewVersionedTypedObjectTypeObject(runtime.NewVersionedTypedObjectTypeByFormatVersion[RepositorySpec](name, fmt), opts...) } //////////////////////////////////////////////////////////////////////////////// diff --git a/api/credentials/internal/repotypes.go b/api/credentials/internal/repotypes.go index dafe999f3..3d2ddad17 100644 --- a/api/credentials/internal/repotypes.go +++ b/api/credentials/internal/repotypes.go @@ -13,7 +13,7 @@ import ( ) type RepositoryType interface { - descriptivetype.TypedObjectType[RepositorySpec] + descriptivetype.VersionedTypedObjectType[RepositorySpec] } type RepositorySpec interface { @@ -28,22 +28,22 @@ type ( ) type RepositoryTypeScheme interface { - descriptivetype.TypeScheme[RepositorySpec, RepositoryType] + descriptivetype.VersionedTypeScheme[RepositorySpec, RepositoryType] } -type _Scheme = descriptivetype.TypeScheme[RepositorySpec, RepositoryType] +type _Scheme = descriptivetype.VersionedTypeScheme[RepositorySpec, RepositoryType] type repositoryTypeScheme struct { _Scheme } func NewRepositoryTypeScheme(defaultDecoder RepositorySpecDecoder, base ...RepositoryTypeScheme) RepositoryTypeScheme { - scheme := descriptivetype.MustNewDefaultTypeScheme[RepositorySpec, RepositoryType, RepositoryTypeScheme]("Credential provider", nil, &UnknownRepositorySpec{}, true, defaultDecoder, utils.Optional(base...)) + scheme := descriptivetype.MustNewDefaultVersionedTypeScheme[RepositorySpec, RepositoryType, RepositoryTypeScheme]("Credential provider", nil, &UnknownRepositorySpec{}, true, defaultDecoder, utils.Optional(base...)) return &repositoryTypeScheme{scheme} } func NewStrictRepositoryTypeScheme(base ...RepositoryTypeScheme) runtime.VersionedTypeRegistry[RepositorySpec, RepositoryType] { - scheme := descriptivetype.MustNewDefaultTypeScheme[RepositorySpec, RepositoryType, RepositoryTypeScheme]("Credential provider", nil, nil, false, nil, utils.Optional(base...)) + scheme := descriptivetype.MustNewDefaultVersionedTypeScheme[RepositorySpec, RepositoryType, RepositoryTypeScheme]("Credential provider", nil, nil, false, nil, utils.Optional(base...)) return &repositoryTypeScheme{scheme} } diff --git a/api/ocm/cpi/accspeccpi/accesstypes.go b/api/ocm/cpi/accspeccpi/accesstypes.go index e71fcc9b8..e9a954d2f 100644 --- a/api/ocm/cpi/accspeccpi/accesstypes.go +++ b/api/ocm/cpi/accspeccpi/accesstypes.go @@ -32,13 +32,13 @@ func MustNewAccessSpecMultiFormatVersion(kind string, formats AccessSpecFormatVe } func NewAccessSpecType[I AccessSpec](name string, opts ...AccessSpecTypeOption) AccessType { - return flagsetscheme.NewTypedObjectTypeObject[AccessSpec](runtime.NewVersionedTypedObjectType[AccessSpec, I](name), opts...) + return flagsetscheme.NewVersionedTypedObjectTypeObject[AccessSpec](runtime.NewVersionedTypedObjectType[AccessSpec, I](name), opts...) } func NewAccessSpecTypeByConverter[I AccessSpec, V runtime.VersionedTypedObject](name string, converter runtime.Converter[I, V], opts ...AccessSpecTypeOption) AccessType { - return flagsetscheme.NewTypedObjectTypeObject[AccessSpec](runtime.NewVersionedTypedObjectTypeByConverter[AccessSpec, I, V](name, converter), opts...) + return flagsetscheme.NewVersionedTypedObjectTypeObject[AccessSpec](runtime.NewVersionedTypedObjectTypeByConverter[AccessSpec, I, V](name, converter), opts...) } func NewAccessSpecTypeByFormatVersion(name string, fmt runtime.FormatVersion[AccessSpec], opts ...AccessSpecTypeOption) AccessType { - return flagsetscheme.NewTypedObjectTypeObject[AccessSpec](runtime.NewVersionedTypedObjectTypeByFormatVersion[AccessSpec](name, fmt), opts...) + return flagsetscheme.NewVersionedTypedObjectTypeObject[AccessSpec](runtime.NewVersionedTypedObjectTypeByFormatVersion[AccessSpec](name, fmt), opts...) } diff --git a/api/ocm/extensions/labels/routingslip/internal/entrytypes.go b/api/ocm/extensions/labels/routingslip/internal/entrytypes.go index dbb7f4205..f70f325b5 100644 --- a/api/ocm/extensions/labels/routingslip/internal/entrytypes.go +++ b/api/ocm/extensions/labels/routingslip/internal/entrytypes.go @@ -41,18 +41,18 @@ type ( //////////////////////////////////////////////////////////////////////////////// -type EntryTypeScheme = flagsetscheme.ExtendedTypeScheme[Entry, EntryType, flagsets.ExplicitlyTypedConfigTypeOptionSetConfigProvider] +type EntryTypeScheme = flagsetscheme.ExtendedProviderTypeScheme[Entry, EntryType, flagsets.ExplicitlyTypedConfigTypeOptionSetConfigProvider] -func unwrapTypeScheme(s EntryTypeScheme) flagsetscheme.TypeScheme[Entry, EntryType] { +func unwrapTypeScheme(s EntryTypeScheme) flagsetscheme.VersionedTypeScheme[Entry, EntryType] { return s.Unwrap() } func NewEntryTypeScheme(base ...EntryTypeScheme) EntryTypeScheme { - return flagsetscheme.NewTypeSchemeWrapper[Entry, EntryType, flagsets.ExplicitlyTypedConfigTypeOptionSetConfigProvider](flagsetscheme.NewTypeScheme[Entry, EntryType, flagsetscheme.TypeScheme[Entry, EntryType]]("Entry type", "entry", "", "routing slip entry specification", "Entry Specification Options", &UnknownEntry{}, true, sliceutils.Transform(base, unwrapTypeScheme)...)) + return flagsetscheme.NewVersionedTypeSchemeWrapper[Entry, EntryType, flagsets.ExplicitlyTypedConfigTypeOptionSetConfigProvider](flagsetscheme.NewVersionedTypeScheme[Entry, EntryType, flagsetscheme.VersionedTypeScheme[Entry, EntryType]]("Entry type", "entry", "", "routing slip entry specification", "Entry Specification Options", &UnknownEntry{}, true, sliceutils.Transform(base, unwrapTypeScheme)...)) } func NewStrictEntryTypeScheme(base ...EntryTypeScheme) EntryTypeScheme { - return flagsetscheme.NewTypeSchemeWrapper[Entry, EntryType, flagsets.ExplicitlyTypedConfigTypeOptionSetConfigProvider](flagsetscheme.NewTypeScheme[Entry, EntryType, flagsetscheme.TypeScheme[Entry, EntryType]]("Entry type", "entry", "", "routing slip entry specification", "Entry Specification Options", nil, false, sliceutils.Transform(base, unwrapTypeScheme)...)) + return flagsetscheme.NewVersionedTypeSchemeWrapper[Entry, EntryType, flagsets.ExplicitlyTypedConfigTypeOptionSetConfigProvider](flagsetscheme.NewVersionedTypeScheme[Entry, EntryType, flagsetscheme.VersionedTypeScheme[Entry, EntryType]]("Entry type", "entry", "", "routing slip entry specification", "Entry Specification Options", nil, false, sliceutils.Transform(base, unwrapTypeScheme)...)) } func CreateEntry(t runtime.TypedObject) (Entry, error) { diff --git a/api/ocm/extensions/labels/routingslip/spi/support.go b/api/ocm/extensions/labels/routingslip/spi/support.go index b0e50ca24..4dc95f32c 100644 --- a/api/ocm/extensions/labels/routingslip/spi/support.go +++ b/api/ocm/extensions/labels/routingslip/spi/support.go @@ -26,15 +26,15 @@ func MustNewEntryMultiFormatVersion(kind string, formats EntryFormatVersionRegis //////////////////////////////////////////////////////////////////////////////// func NewEntryType[I Entry](name string, opts ...EntryTypeOption) EntryType { - return flagsetscheme.NewTypedObjectTypeObject[Entry](runtime.NewVersionedTypedObjectType[Entry, I](name), opts...) + return flagsetscheme.NewVersionedTypedObjectTypeObject[Entry](runtime.NewVersionedTypedObjectType[Entry, I](name), opts...) } func NewEntryTypeByConverter[I Entry, V runtime.VersionedTypedObject](name string, converter runtime.Converter[I, V], opts ...EntryTypeOption) EntryType { - return flagsetscheme.NewTypedObjectTypeObject[Entry](runtime.NewVersionedTypedObjectTypeByConverter[Entry, I, V](name, converter), opts...) + return flagsetscheme.NewVersionedTypedObjectTypeObject[Entry](runtime.NewVersionedTypedObjectTypeByConverter[Entry, I, V](name, converter), opts...) } func NewEntryTypeByFormatVersion(name string, fmt runtime.FormatVersion[Entry], opts ...EntryTypeOption) EntryType { - return flagsetscheme.NewTypedObjectTypeObject[Entry](runtime.NewVersionedTypedObjectTypeByFormatVersion[Entry](name, fmt), opts...) + return flagsetscheme.NewVersionedTypedObjectTypeObject[Entry](runtime.NewVersionedTypedObjectTypeByFormatVersion[Entry](name, fmt), opts...) } //////////////////////////////////////////////////////////////////////////////// diff --git a/api/ocm/extensions/pubsub/interface.go b/api/ocm/extensions/pubsub/interface.go index 744a14a82..f7fc402f1 100644 --- a/api/ocm/extensions/pubsub/interface.go +++ b/api/ocm/extensions/pubsub/interface.go @@ -9,7 +9,6 @@ import ( "github.com/mandelsoft/goutils/errors" "github.com/mandelsoft/goutils/general" "github.com/mandelsoft/goutils/generics" - "github.com/mandelsoft/goutils/optionutils" "github.com/modern-go/reflect2" "ocm.software/ocm/api/ocm/cpi" @@ -33,7 +32,7 @@ func WithDesciption(desc string) Option { //////////////////////////////////////////////////////////////////////////////// -type PubSubType descriptivetype.TypedObjectType[PubSubSpec] +type PubSubType descriptivetype.VersionedTypedObjectType[PubSubSpec] // PubSubSpec is the interface publish/subscribe specifications // must fulfill. The main task is to map the specification @@ -61,14 +60,14 @@ type PubSubMethod interface { // PubSub types. A PubSub type is finally able to // provide an implementation for notifying a dedicated // PubSub instance. -type TypeScheme descriptivetype.TypeScheme[PubSubSpec, PubSubType] +type TypeScheme descriptivetype.VersionedTypeScheme[PubSubSpec, PubSubType] func NewTypeScheme(base ...TypeScheme) TypeScheme { - return descriptivetype.NewTypeScheme[PubSubSpec, PubSubType, TypeScheme]("PubSub type", nil, &UnknownPubSubSpec{}, false, base...) + return descriptivetype.NewVersionedTypeScheme[PubSubSpec, PubSubType, TypeScheme]("PubSub type", nil, &UnknownPubSubSpec{}, false, base...) } func NewStrictTypeScheme(base ...TypeScheme) runtime.VersionedTypeRegistry[PubSubSpec, PubSubType] { - return descriptivetype.NewTypeScheme[PubSubSpec, PubSubType, TypeScheme]("PubSub type", nil, &UnknownPubSubSpec{}, false, base...) + return descriptivetype.NewVersionedTypeScheme[PubSubSpec, PubSubType, TypeScheme]("PubSub type", nil, &UnknownPubSubSpec{}, false, base...) } // DefaultTypeScheme contains all globally known PubSub serializers. @@ -83,10 +82,7 @@ func CreatePubSubSpec(t runtime.TypedObject) (PubSubSpec, error) { } func NewPubSubType[I PubSubSpec](name string, opts ...Option) PubSubType { - t := descriptivetype.NewTypedObjectTypeObject[PubSubSpec](runtime.NewVersionedTypedObjectType[PubSubSpec, I](name)) - ta := descriptivetype.NewTypeObjectTarget[PubSubSpec](t) - optionutils.ApplyOptions[descriptivetype.OptionTarget](ta, opts...) - return t + return descriptivetype.NewVersionedTypedObjectTypeObject[PubSubSpec](runtime.NewVersionedTypedObjectType[PubSubSpec, I](name), opts...) } //////////////////////////////////////////////////////////////////////////////// diff --git a/api/ocm/internal/accesstypes.go b/api/ocm/internal/accesstypes.go index c4c8d88d5..07c68d927 100644 --- a/api/ocm/internal/accesstypes.go +++ b/api/ocm/internal/accesstypes.go @@ -106,14 +106,14 @@ type AccessMethod interface { AsBlobAccess() BlobAccess } -type AccessTypeScheme flagsetscheme.TypeScheme[AccessSpec, AccessType] +type AccessTypeScheme flagsetscheme.VersionedTypeScheme[AccessSpec, AccessType] func NewAccessTypeScheme(base ...AccessTypeScheme) AccessTypeScheme { - return flagsetscheme.NewTypeScheme[AccessSpec, AccessType, AccessTypeScheme]("Access type", "access", "accessType", "blob access specification", "Access Specification Options", &UnknownAccessSpec{}, true, base...) + return flagsetscheme.NewVersionedTypeScheme[AccessSpec, AccessType, AccessTypeScheme]("Access type", "access", "accessType", "blob access specification", "Access Specification Options", &UnknownAccessSpec{}, true, base...) } func NewStrictAccessTypeScheme(base ...AccessTypeScheme) runtime.VersionedTypeRegistry[AccessSpec, AccessType] { - return flagsetscheme.NewTypeScheme[AccessSpec, AccessType, AccessTypeScheme]("Access type", "access", "accessType", "blob access specification", "Access Specification Options", nil, false, base...) + return flagsetscheme.NewVersionedTypeScheme[AccessSpec, AccessType, AccessTypeScheme]("Access type", "access", "accessType", "blob access specification", "Access Specification Options", nil, false, base...) } // DefaultAccessTypeScheme contains all globally known access serializer. diff --git a/api/utils/cobrautils/flagsets/flagsetscheme/common.go b/api/utils/cobrautils/flagsets/flagsetscheme/common.go new file mode 100644 index 000000000..c6c9b80b7 --- /dev/null +++ b/api/utils/cobrautils/flagsets/flagsetscheme/common.go @@ -0,0 +1,19 @@ +package flagsetscheme + +import ( + "ocm.software/ocm/api/utils/cobrautils/flagsets" +) + +type TypeInfo interface { + ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler + Description() string + Format() string +} + +type typeInfoImpl struct { + handler flagsets.ConfigOptionTypeSetHandler +} + +func (i *typeInfoImpl) ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler { + return i.handler +} diff --git a/api/utils/cobrautils/flagsets/flagsetscheme/types_options.go b/api/utils/cobrautils/flagsets/flagsetscheme/options.go similarity index 69% rename from api/utils/cobrautils/flagsets/flagsetscheme/types_options.go rename to api/utils/cobrautils/flagsets/flagsetscheme/options.go index f6283b976..f035fbd84 100644 --- a/api/utils/cobrautils/flagsets/flagsetscheme/types_options.go +++ b/api/utils/cobrautils/flagsets/flagsetscheme/options.go @@ -7,11 +7,27 @@ import ( "ocm.software/ocm/api/utils/runtime/descriptivetype" ) +// OptionTargetWrapper is used as target for option functions, it provides +// setters for fields, which should not be modifiable for a final type object. +type OptionTargetWrapper[T any] struct { + target T + info *typeInfoImpl +} + +func NewOptionTargetWrapper[T any](target T, info *typeInfoImpl) *OptionTargetWrapper[T] { + return &OptionTargetWrapper[T]{ + target: target, + info: info, + } +} + +func (t OptionTargetWrapper[E]) SetConfigHandler(value flagsets.ConfigOptionTypeSetHandler) { + t.info.handler = value +} + //////////////////////////////////////////////////////////////////////////////// -// Access Type Options type OptionTarget interface { - descriptivetype.OptionTarget SetConfigHandler(flagsets.ConfigOptionTypeSetHandler) } diff --git a/api/utils/cobrautils/flagsets/flagsetscheme/scheme.go b/api/utils/cobrautils/flagsets/flagsetscheme/scheme.go index f0ed2ea6c..4698e3f46 100644 --- a/api/utils/cobrautils/flagsets/flagsetscheme/scheme.go +++ b/api/utils/cobrautils/flagsets/flagsetscheme/scheme.go @@ -8,19 +8,11 @@ import ( "ocm.software/ocm/api/utils/runtime/descriptivetype" ) -// VersionTypedObjectType is the appropriately extended type interface -// based on runtime.VersionTypedObjectType. -type VersionTypedObjectType[T runtime.VersionedTypedObject] interface { - descriptivetype.TypedObjectType[T] - - ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler -} - //////////////////////////////////////////////////////////////////////////////// -// ExtendedTypeScheme is the appropriately extended scheme interface based on +// ExtendedProviderTypeScheme is the appropriately extended scheme interface based on // runtime.TypeScheme supporting an extended config provider interface. -type ExtendedTypeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], P flagsets.ConfigTypeOptionSetConfigProvider] interface { +type ExtendedProviderTypeScheme[T runtime.TypedObject, R TypedObjectType[T], P flagsets.ConfigTypeOptionSetConfigProvider] interface { descriptivetype.TypeScheme[T, R] CreateConfigTypeSetConfigProvider() P @@ -28,11 +20,11 @@ type ExtendedTypeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType Unwrap() TypeScheme[T, R] } -type _TypeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T]] interface { +type _TypeScheme[T runtime.TypedObject, R TypedObjectType[T]] interface { TypeScheme[T, R] } -type typeSchemeWrapper[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], P flagsets.ConfigTypeOptionSetConfigProvider] struct { +type typeSchemeWrapper[T runtime.TypedObject, R TypedObjectType[T], P flagsets.ConfigTypeOptionSetConfigProvider] struct { _TypeScheme[T, R] } @@ -44,24 +36,35 @@ func (s *typeSchemeWrapper[T, R, P]) Unwrap() TypeScheme[T, R] { return s._TypeScheme } +// NewVersionedTypeSchemeWrapper wraps a [VersionedTypeScheme] into a scheme returning a specialized config provider +// by casting the result. The type scheme constructor provides different implementations based on its +// arguments. This method here can be used to provide a type scheme returning the correct type. +func NewVersionedTypeSchemeWrapper[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], P flagsets.ConfigTypeOptionSetConfigProvider](s VersionedTypeScheme[T, R]) ExtendedProviderTypeScheme[T, R, P] { + return &typeSchemeWrapper[T, R, P]{s} +} + // NewTypeSchemeWrapper wraps a [TypeScheme] into a scheme returning a specialized config provider // by casting the result. The type scheme constructor provides different implementations based on its // arguments. This method here can be used to provide a type scheme returning the correct type. -func NewTypeSchemeWrapper[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], P flagsets.ConfigTypeOptionSetConfigProvider](s TypeScheme[T, R]) ExtendedTypeScheme[T, R, P] { +func NewTypeSchemeWrapper[T runtime.TypedObject, R TypedObjectType[T], P flagsets.ConfigTypeOptionSetConfigProvider](s TypeScheme[T, R]) ExtendedProviderTypeScheme[T, R, P] { return &typeSchemeWrapper[T, R, P]{s} } -// TypeScheme is the appropriately extended scheme interface based on +// VersionedTypeScheme is the appropriately extended scheme interface based on // runtime.TypeScheme. -type TypeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T]] interface { - ExtendedTypeScheme[T, R, flagsets.ConfigTypeOptionSetConfigProvider] +type VersionedTypeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T]] interface { + ExtendedProviderTypeScheme[T, R, flagsets.ConfigTypeOptionSetConfigProvider] +} + +type TypeScheme[T runtime.TypedObject, R TypedObjectType[T]] interface { + ExtendedProviderTypeScheme[T, R, flagsets.ConfigTypeOptionSetConfigProvider] } -type _typeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T]] interface { +type _typeScheme[T runtime.TypedObject, R TypedObjectType[T]] interface { descriptivetype.TypeScheme[T, R] } -type typeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], S TypeScheme[T, R]] struct { +type typeScheme[T runtime.TypedObject, R TypedObjectType[T], S TypeScheme[T, R]] struct { cfgname string description string group string @@ -69,16 +72,29 @@ type typeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], S T _typeScheme[T, R] } -func flagExtender[T runtime.VersionedTypedObject, R VersionTypedObjectType[T]](ty R) string { +func flagExtender[T runtime.TypedObject, R TypedObjectType[T]](ty R) string { if h := ty.ConfigOptionTypeSetHandler(); h != nil { return utils.IndentLines(flagsets.FormatConfigOptions(h), " ") } return "" } -// NewTypeScheme provides an TypeScheme implementation based on the interfaces +// NewVersionedTypeScheme provides an VersionedTypeScheme implementation based on the interfaces +// and the default runtime.TypeScheme implementation. +func NewVersionedTypeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], S TypeScheme[T, R]](kindname string, cfgname, typeOption, desc, group string, unknown runtime.Unstructured, acceptUnknown bool, base ...S) VersionedTypeScheme[T, R] { + scheme := descriptivetype.NewVersionedTypeScheme[T, R](kindname, flagExtender[T, R], unknown, acceptUnknown, utils.Optional(base...)) + return &typeScheme[T, R, S]{ + cfgname: cfgname, + description: desc, + group: group, + typeOption: typeOption, + _typeScheme: scheme, + } +} + +// NewTypeScheme provides an VersionedTypeScheme implementation based on the interfaces // and the default runtime.TypeScheme implementation. -func NewTypeScheme[T runtime.VersionedTypedObject, R VersionTypedObjectType[T], S TypeScheme[T, R]](kindname string, cfgname, typeOption, desc, group string, unknown runtime.Unstructured, acceptUnknown bool, base ...S) TypeScheme[T, R] { +func NewTypeScheme[T runtime.TypedObject, R TypedObjectType[T], S TypeScheme[T, R]](kindname string, cfgname, typeOption, desc, group string, unknown runtime.Unstructured, acceptUnknown bool, base ...S) TypeScheme[T, R] { scheme := descriptivetype.NewTypeScheme[T, R](kindname, flagExtender[T, R], unknown, acceptUnknown, utils.Optional(base...)) return &typeScheme[T, R, S]{ cfgname: cfgname, @@ -110,8 +126,8 @@ func (t *typeScheme[T, R, S]) CreateConfigTypeSetConfigProvider() flagsets.Confi } } if t.BaseScheme() != nil { - base := t.BaseScheme() - for _, s := range base.(S).CreateConfigTypeSetConfigProvider().OptionTypeSets() { + base := t.BaseScheme().(S) + for _, s := range base.CreateConfigTypeSetConfigProvider().OptionTypeSets() { if prov.GetTypeSet(s.GetName()) == nil { err := prov.AddTypeSet(s) if err != nil { diff --git a/api/utils/cobrautils/flagsets/flagsetscheme/type.go b/api/utils/cobrautils/flagsets/flagsetscheme/type.go new file mode 100644 index 000000000..2f82ea96b --- /dev/null +++ b/api/utils/cobrautils/flagsets/flagsetscheme/type.go @@ -0,0 +1,41 @@ +package flagsetscheme + +import ( + "github.com/mandelsoft/goutils/optionutils" + + "ocm.software/ocm/api/utils/cobrautils/flagsets" + "ocm.software/ocm/api/utils/runtime" + "ocm.software/ocm/api/utils/runtime/descriptivetype" +) + +// TypedObjectType is the appropriately extended type interface +// based on runtime.TypedObjectType. +type TypedObjectType[T runtime.TypedObject] interface { + descriptivetype.TypedObjectType[T] + + ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler +} + +//////////////////////////////////////////////////////////////////////////////// + +type TypedObjectTypeObject[E runtime.VersionedTypedObject] struct { + *descriptivetype.TypedObjectTypeObject[E] + typeInfoImpl + validator func(E) error +} + +func NewTypedObjectTypeObject[E runtime.VersionedTypedObject](vt runtime.TypedObjectType[E], opts ...TypeOption) *TypedObjectTypeObject[E] { + target := &TypedObjectTypeObject[E]{ + TypedObjectTypeObject: descriptivetype.NewTypedObjectTypeObject[E](vt, optionutils.FilterMappedOptions[descriptivetype.OptionTarget](opts...)...), + } + t := NewOptionTargetWrapper[*TypedObjectTypeObject[E]](target, &target.typeInfoImpl) + optionutils.ApplyOptions[OptionTarget](t, opts...) + return t.target +} + +func (t *TypedObjectTypeObject[E]) Validate(e E) error { + if t.validator == nil { + return nil + } + return t.validator(e) +} diff --git a/api/utils/cobrautils/flagsets/flagsetscheme/types.go b/api/utils/cobrautils/flagsets/flagsetscheme/types.go deleted file mode 100644 index 1cf41b482..000000000 --- a/api/utils/cobrautils/flagsets/flagsetscheme/types.go +++ /dev/null @@ -1,62 +0,0 @@ -package flagsetscheme - -import ( - "github.com/mandelsoft/goutils/optionutils" - - "ocm.software/ocm/api/utils/cobrautils/flagsets" - "ocm.software/ocm/api/utils/runtime" - "ocm.software/ocm/api/utils/runtime/descriptivetype" -) - -type additionalTypeInfo interface { - ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler - Description() string - Format() string -} - -type TypedObjectTypeObject[E runtime.VersionedTypedObject] struct { - *descriptivetype.TypedObjectTypeObject[E] - handler flagsets.ConfigOptionTypeSetHandler - validator func(E) error -} - -var _ additionalTypeInfo = (*TypedObjectTypeObject[runtime.VersionedTypedObject])(nil) - -func NewTypedObjectTypeObject[E runtime.VersionedTypedObject](vt runtime.VersionedTypedObjectType[E], opts ...TypeOption) *TypedObjectTypeObject[E] { - t := NewTypeObjectTarget[E](&TypedObjectTypeObject[E]{ - TypedObjectTypeObject: descriptivetype.NewTypedObjectTypeObject[E](vt), - }) - optionutils.ApplyOptions[OptionTarget](t, opts...) - return t.target -} - -func (t *TypedObjectTypeObject[E]) ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler { - return t.handler -} - -func (t *TypedObjectTypeObject[E]) Validate(e E) error { - if t.validator == nil { - return nil - } - return t.validator(e) -} - -//////////////////////////////////////////////////////////////////////////////// - -// TypeObjectTarget is used as target for option functions, it provides -// setters for fields, which should nor be modifiable for a final type object. -type TypeObjectTarget[E runtime.VersionedTypedObject] struct { - *descriptivetype.TypeObjectTarget[E] - target *TypedObjectTypeObject[E] -} - -func NewTypeObjectTarget[E runtime.VersionedTypedObject](target *TypedObjectTypeObject[E]) *TypeObjectTarget[E] { - return &TypeObjectTarget[E]{ - target: target, - TypeObjectTarget: descriptivetype.NewTypeObjectTarget[E](target.TypedObjectTypeObject), - } -} - -func (t TypeObjectTarget[E]) SetConfigHandler(value flagsets.ConfigOptionTypeSetHandler) { - t.target.handler = value -} diff --git a/api/utils/cobrautils/flagsets/flagsetscheme/versioned.go b/api/utils/cobrautils/flagsets/flagsetscheme/versioned.go new file mode 100644 index 000000000..0ee978388 --- /dev/null +++ b/api/utils/cobrautils/flagsets/flagsetscheme/versioned.go @@ -0,0 +1,43 @@ +package flagsetscheme + +import ( + "github.com/mandelsoft/goutils/optionutils" + + "ocm.software/ocm/api/utils/cobrautils/flagsets" + "ocm.software/ocm/api/utils/runtime" + "ocm.software/ocm/api/utils/runtime/descriptivetype" +) + +// VersionTypedObjectType is the appropriately extended type interface +// based on runtime.VersionTypedObjectType. +type VersionTypedObjectType[T runtime.VersionedTypedObject] interface { + descriptivetype.VersionedTypedObjectType[T] + + ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler +} + +//////////////////////////////////////////////////////////////////////////////// + +type VersionedTypedObjectTypeObject[E runtime.VersionedTypedObject] struct { + *descriptivetype.VersionedTypedObjectTypeObject[E] + typeInfoImpl + validator func(E) error +} + +var _ TypeInfo = (*VersionedTypedObjectTypeObject[runtime.VersionedTypedObject])(nil) + +func NewVersionedTypedObjectTypeObject[E runtime.VersionedTypedObject](vt runtime.VersionedTypedObjectType[E], opts ...TypeOption) *VersionedTypedObjectTypeObject[E] { + target := &VersionedTypedObjectTypeObject[E]{ + VersionedTypedObjectTypeObject: descriptivetype.NewVersionedTypedObjectTypeObject[E](vt, optionutils.FilterMappedOptions[descriptivetype.OptionTarget](opts...)...), + } + t := NewOptionTargetWrapper[*VersionedTypedObjectTypeObject[E]](target, &target.typeInfoImpl) + optionutils.ApplyOptions[OptionTarget](t, opts...) + return t.target +} + +func (t *VersionedTypedObjectTypeObject[E]) Validate(e E) error { + if t.validator == nil { + return nil + } + return t.validator(e) +} diff --git a/api/utils/runtime/descriptivetype/common.go b/api/utils/runtime/descriptivetype/common.go new file mode 100644 index 000000000..b42a95a3c --- /dev/null +++ b/api/utils/runtime/descriptivetype/common.go @@ -0,0 +1,27 @@ +package descriptivetype + +// TypeInfo is the interface extension for descriptive types. +type TypeInfo interface { + Description() string + Format() string +} + +type typeInfoImpl struct { + description string + format string +} + +var _ TypeInfo = (*typeInfoImpl)(nil) + +func (i *typeInfoImpl) Description() string { + return i.description +} + +func (i *typeInfoImpl) Format() string { + return i.format +} + +// DescriptionExtender provides an additional description for a type object +// which is appended to the format description in the scheme description +// for the type in question. +type DescriptionExtender[T any] func(t T) string diff --git a/api/utils/runtime/descriptivetype/options.go b/api/utils/runtime/descriptivetype/options.go index 730b05a4b..6dab03c22 100644 --- a/api/utils/runtime/descriptivetype/options.go +++ b/api/utils/runtime/descriptivetype/options.go @@ -2,28 +2,31 @@ package descriptivetype import ( "github.com/mandelsoft/goutils/optionutils" - - "ocm.software/ocm/api/utils/runtime" ) //////////////////////////////////////////////////////////////////////////////// -// TypeObjectTarget is used as target for option functions, it provides +// OptionTargetWrapper is used as target for option functions, it provides // setters for fields, which should not be modifiable for a final type object. -type TypeObjectTarget[E runtime.VersionedTypedObject] struct { - target *TypedObjectTypeObject[E] +type OptionTargetWrapper[T any] struct { + target T + info *typeInfoImpl +} + +func NewOptionTargetWrapper[T any](target T, info *typeInfoImpl) *OptionTargetWrapper[T] { + return &OptionTargetWrapper[T]{target, info} } -func NewTypeObjectTarget[E runtime.VersionedTypedObject](target *TypedObjectTypeObject[E]) *TypeObjectTarget[E] { - return &TypeObjectTarget[E]{target} +func (t *OptionTargetWrapper[T]) SetDescription(value string) { + t.info.description = value } -func (t *TypeObjectTarget[E]) SetDescription(value string) { - t.target.description = value +func (t *OptionTargetWrapper[T]) SetFormat(value string) { + t.info.format = value } -func (t *TypeObjectTarget[E]) SetFormat(value string) { - t.target.format = value +func (t *OptionTargetWrapper[T]) Target() T { + return t.target } //////////////////////////////////////////////////////////////////////////////// diff --git a/api/utils/runtime/descriptivetype/scheme.go b/api/utils/runtime/descriptivetype/scheme.go new file mode 100644 index 000000000..193fa9797 --- /dev/null +++ b/api/utils/runtime/descriptivetype/scheme.go @@ -0,0 +1,132 @@ +package descriptivetype + +import ( + "fmt" + "strings" + + "ocm.software/ocm/api/utils" + "ocm.software/ocm/api/utils/runtime" +) + +// TypeScheme is the appropriately extended scheme interface based on +// runtime.TypeScheme. Based on the additional type info a complete +// scheme description can be created calling the Describe method. +type TypeScheme[T runtime.TypedObject, R TypedObjectType[T]] interface { + runtime.TypeScheme[T, R] + + Describe() string +} + +type _typeScheme[T runtime.TypedObject, R runtime.TypedObjectType[T]] interface { + runtime.TypeScheme[T, R] // for goland to be able to accept extender argument type +} + +type typeScheme[T runtime.TypedObject, R TypedObjectType[T], S runtime.TypeScheme[T, R]] struct { + name string + extender DescriptionExtender[R] + versioned bool + _typeScheme[T, R] +} + +func MustNewDefaultTypeScheme[T runtime.TypedObject, R TypedObjectType[T], S TypeScheme[T, R]](name string, extender DescriptionExtender[R], unknown runtime.Unstructured, acceptUnknown bool, defaultdecoder runtime.TypedObjectDecoder[T], base ...TypeScheme[T, R]) TypeScheme[T, R] { + scheme := runtime.MustNewDefaultTypeScheme[T, R](unknown, acceptUnknown, defaultdecoder, utils.Optional(base...)) + return &typeScheme[T, R, S]{ + name: name, + extender: extender, + _typeScheme: scheme, + } +} + +// NewTypeScheme provides an TypeScheme implementation based on the interfaces +// and the default runtime.TypeScheme implementation. +func NewTypeScheme[T runtime.TypedObject, R TypedObjectType[T], S TypeScheme[T, R]](name string, extender DescriptionExtender[R], unknown runtime.Unstructured, acceptUnknown bool, base ...S) TypeScheme[T, R] { + scheme := runtime.MustNewDefaultTypeScheme[T, R](unknown, acceptUnknown, nil, utils.Optional(base...)) + return &typeScheme[T, R, S]{ + name: name, + extender: extender, + _typeScheme: scheme, + } +} + +//////////////////////////////////////////////////////////////////////////////// + +func (t *typeScheme[T, R, S]) KnownTypes() runtime.KnownTypes[T, R] { + return t._typeScheme.KnownTypes() // Goland +} + +func (t *typeScheme[T, R, S]) Describe() string { + s := "" + type method struct { + desc string + versions map[string]string + more string + } + + descs := map[string]*method{} + + // gather info for kinds and versions + for _, n := range t.KnownTypeNames() { + var kind, vers string + if t.versioned { + kind, vers = runtime.KindVersion(n) + } else { + kind = n + } + + info := descs[kind] + if info == nil { + info = &method{versions: map[string]string{}} + descs[kind] = info + } + + if vers == "" { + vers = "v1" + } + if _, ok := info.versions[vers]; !ok { + info.versions[vers] = "" + } + + ty := t.GetType(n) + + if t.extender != nil { + more := t.extender(ty) + if more != "" { + info.more = more + } + } + desc := ty.Description() + if desc != "" { + info.desc = desc + } + + desc = ty.Format() + if desc != "" { + info.versions[vers] = desc + } + } + + for _, tn := range utils.StringMapKeys(descs) { + info := descs[tn] + desc := strings.Trim(info.desc, "\n") + if desc != "" { + s = fmt.Sprintf("%s\n- %s %s\n\n%s\n\n", s, t.name, tn, utils.IndentLines(desc, " ")) + + format := "" + for _, f := range utils.StringMapKeys(info.versions) { + desc = strings.Trim(info.versions[f], "\n") + if desc != "" { + if t.versioned { + format = fmt.Sprintf("%s\n- Version %s\n\n%s\n", format, f, utils.IndentLines(desc, " ")) + } else { + s += utils.IndentLines(desc, " ") + } + } + } + if format != "" { + s += fmt.Sprintf(" The following versions are supported:\n%s\n", strings.Trim(utils.IndentLines(format, " "), "\n")) + } + } + s += info.more + } + return s +} diff --git a/api/utils/runtime/descriptivetype/type.go b/api/utils/runtime/descriptivetype/type.go index 6a5ad78ee..c58508331 100644 --- a/api/utils/runtime/descriptivetype/type.go +++ b/api/utils/runtime/descriptivetype/type.go @@ -1,175 +1,34 @@ package descriptivetype import ( - "fmt" - "strings" - - "ocm.software/ocm/api/utils" "ocm.software/ocm/api/utils/runtime" ) -// DescriptionExtender provides an additional description for a type object -// which is appended to the format description in the scheme description -// for the type in question. -type DescriptionExtender[T any] func(t T) string - // TypedObjectType is the appropriately extended type interface // based on runtime.VersionTypedObjectType providing support for a functional and // format description. -type TypedObjectType[T runtime.VersionedTypedObject] interface { - runtime.VersionedTypedObjectType[T] - - Description() string - Format() string +type TypedObjectType[T runtime.TypedObject] interface { + runtime.TypedObjectType[T] + TypeInfo } //////////////////////////////////////////////////////////////////////////////// -// TypeScheme is the appropriately extended scheme interface based on -// runtime.TypeScheme. Based on the additional type info a complete -// scheme description can be created calling the Describe method. -type TypeScheme[T runtime.VersionedTypedObject, R TypedObjectType[T]] interface { - runtime.TypeScheme[T, R] - - Describe() string -} - -type _typeScheme[T runtime.VersionedTypedObject, R TypedObjectType[T]] interface { - runtime.TypeScheme[T, R] // for goland to be able to accept extender argument type -} - -type typeScheme[T runtime.VersionedTypedObject, R TypedObjectType[T], S TypeScheme[T, R]] struct { - name string - extender DescriptionExtender[R] - _typeScheme[T, R] -} - -func MustNewDefaultTypeScheme[T runtime.VersionedTypedObject, R TypedObjectType[T], S TypeScheme[T, R]](name string, extender DescriptionExtender[R], unknown runtime.Unstructured, acceptUnknown bool, defaultdecoder runtime.TypedObjectDecoder[T], base ...TypeScheme[T, R]) TypeScheme[T, R] { - scheme := runtime.MustNewDefaultTypeScheme[T, R](unknown, acceptUnknown, defaultdecoder, utils.Optional(base...)) - return &typeScheme[T, R, S]{ - name: name, - extender: extender, - _typeScheme: scheme, - } +type TypedObjectTypeObject[T runtime.TypedObject] struct { + runtime.TypedObjectType[T] + typeInfoImpl + validator func(T) error } -// NewTypeScheme provides an TypeScheme implementation based on the interfaces -// and the default runtime.TypeScheme implementation. -func NewTypeScheme[T runtime.VersionedTypedObject, R TypedObjectType[T], S TypeScheme[T, R]](name string, extender DescriptionExtender[R], unknown runtime.Unstructured, acceptUnknown bool, base ...S) TypeScheme[T, R] { - scheme := runtime.MustNewDefaultTypeScheme[T, R](unknown, acceptUnknown, nil, utils.Optional(base...)) - return &typeScheme[T, R, S]{ - name: name, - extender: extender, - _typeScheme: scheme, - } -} - -func (t *typeScheme[T, R, S]) KnownTypes() runtime.KnownTypes[T, R] { - return t._typeScheme.KnownTypes() // Goland -} - -//////////////////////////////////////////////////////////////////////////////// - -func (t *typeScheme[T, R, S]) Describe() string { - s := "" - type method struct { - desc string - versions map[string]string - more string - } - - descs := map[string]*method{} - - // gather info for kinds and versions - for _, n := range t.KnownTypeNames() { - kind, vers := runtime.KindVersion(n) - - info := descs[kind] - if info == nil { - info = &method{versions: map[string]string{}} - descs[kind] = info - } - - if vers == "" { - vers = "v1" - } - if _, ok := info.versions[vers]; !ok { - info.versions[vers] = "" - } - - ty := t.GetType(n) - - if t.extender != nil { - more := t.extender(ty) - if more != "" { - info.more = more - } - } - desc := ty.Description() - if desc != "" { - info.desc = desc - } - - desc = ty.Format() - if desc != "" { - info.versions[vers] = desc - } +func NewTypedObjectTypeObject[E runtime.VersionedTypedObject](vt runtime.TypedObjectType[E], opts ...Option) *TypedObjectTypeObject[E] { + target := &TypedObjectTypeObject[E]{ + TypedObjectType: vt, } - - for _, tn := range utils.StringMapKeys(descs) { - info := descs[tn] - desc := strings.Trim(info.desc, "\n") - if desc != "" { - s = fmt.Sprintf("%s\n- %s %s\n\n%s\n\n", s, t.name, tn, utils.IndentLines(desc, " ")) - - format := "" - for _, f := range utils.StringMapKeys(info.versions) { - desc = strings.Trim(info.versions[f], "\n") - if desc != "" { - format = fmt.Sprintf("%s\n- Version %s\n\n%s\n", format, f, utils.IndentLines(desc, " ")) - } - } - if format != "" { - s += fmt.Sprintf(" The following versions are supported:\n%s\n", strings.Trim(utils.IndentLines(format, " "), "\n")) - } - } - s += info.more - } - return s -} - -//////////////////////////////////////////////////////////////////////////////// - -type descriptiveTypeInfo interface { - Description() string - Format() string -} - -type TypedObjectTypeObject[T runtime.VersionedTypedObject] struct { - runtime.VersionedTypedObjectType[T] - description string - format string - validator func(T) error -} - -var _ descriptiveTypeInfo = (*TypedObjectTypeObject[runtime.VersionedTypedObject])(nil) - -func NewTypedObjectTypeObject[E runtime.VersionedTypedObject](vt runtime.VersionedTypedObjectType[E], opts ...Option) *TypedObjectTypeObject[E] { - t := NewTypeObjectTarget[E](&TypedObjectTypeObject[E]{ - VersionedTypedObjectType: vt, - }) + t := NewOptionTargetWrapper(target, &target.typeInfoImpl) for _, o := range opts { o.ApplyTo(t) } - return t.target -} - -func (t *TypedObjectTypeObject[T]) Description() string { - return t.description -} - -func (t *TypedObjectTypeObject[T]) Format() string { - return t.format + return target } func (t *TypedObjectTypeObject[T]) Validate(e T) error { diff --git a/api/utils/runtime/descriptivetype/versionedtype.go b/api/utils/runtime/descriptivetype/versionedtype.go new file mode 100644 index 000000000..9c75b8877 --- /dev/null +++ b/api/utils/runtime/descriptivetype/versionedtype.go @@ -0,0 +1,71 @@ +package descriptivetype + +import ( + "ocm.software/ocm/api/utils" + "ocm.software/ocm/api/utils/runtime" +) + +// VersionedTypedObjectType is the appropriately extended type interface +// based on runtime.VersionTypedObjectType providing support for a functional and +// format description. +type VersionedTypedObjectType[T runtime.VersionedTypedObject] interface { + runtime.VersionedTypedObjectType[T] + TypeInfo +} + +//////////////////////////////////////////////////////////////////////////////// + +// VersionedTypeScheme is the appropriately extended scheme interface based on +// runtime.TypeScheme. Based on the additional type info a complete +// scheme description can be created calling the Describe method. +type VersionedTypeScheme[T runtime.VersionedTypedObject, R VersionedTypedObjectType[T]] interface { + TypeScheme[T, R] +} + +func MustNewDefaultVersionedTypeScheme[T runtime.VersionedTypedObject, R VersionedTypedObjectType[T], S VersionedTypeScheme[T, R]](name string, extender DescriptionExtender[R], unknown runtime.Unstructured, acceptUnknown bool, defaultdecoder runtime.TypedObjectDecoder[T], base ...VersionedTypeScheme[T, R]) VersionedTypeScheme[T, R] { + scheme := runtime.MustNewDefaultTypeScheme[T, R](unknown, acceptUnknown, defaultdecoder, utils.Optional(base...)) + return &typeScheme[T, R, S]{ + name: name, + extender: extender, + _typeScheme: scheme, + versioned: true, + } +} + +// NewVersionedTypeScheme provides an TypeScheme implementation based on the interfaces +// and the default runtime.TypeScheme implementation. +func NewVersionedTypeScheme[T runtime.VersionedTypedObject, R VersionedTypedObjectType[T], S VersionedTypeScheme[T, R]](name string, extender DescriptionExtender[R], unknown runtime.Unstructured, acceptUnknown bool, base ...S) VersionedTypeScheme[T, R] { + scheme := runtime.MustNewDefaultTypeScheme[T, R](unknown, acceptUnknown, nil, utils.Optional(base...)) + return &typeScheme[T, R, S]{ + name: name, + extender: extender, + _typeScheme: scheme, + versioned: true, + } +} + +//////////////////////////////////////////////////////////////////////////////// + +type VersionedTypedObjectTypeObject[T runtime.VersionedTypedObject] struct { + runtime.VersionedTypedObjectType[T] + typeInfoImpl + validator func(T) error +} + +func NewVersionedTypedObjectTypeObject[E runtime.VersionedTypedObject](vt runtime.VersionedTypedObjectType[E], opts ...Option) *VersionedTypedObjectTypeObject[E] { + target := &VersionedTypedObjectTypeObject[E]{ + VersionedTypedObjectType: vt, + } + t := NewOptionTargetWrapper(target, &target.typeInfoImpl) + for _, o := range opts { + o.ApplyTo(t) + } + return target +} + +func (t *VersionedTypedObjectTypeObject[T]) Validate(e T) error { + if t.validator == nil { + return nil + } + return t.validator(e) +} diff --git a/cmds/ocm/commands/ocmcmds/common/addhdlrs/comp/elements.go b/cmds/ocm/commands/ocmcmds/common/addhdlrs/comp/elements.go index bd47976aa..6566ad50b 100644 --- a/cmds/ocm/commands/ocmcmds/common/addhdlrs/comp/elements.go +++ b/cmds/ocm/commands/ocmcmds/common/addhdlrs/comp/elements.go @@ -111,11 +111,13 @@ func (h *ResourceSpecHandler) Add(ctx clictx.Context, ictx inputs.Context, elem cd := cv.GetDescriptor() - opts := h.srchandler.GetOptions()[0].(*addhdlrs.Options) - if !opts.Replace { - cd.Resources = nil - cd.Sources = nil - cd.References = nil + if len(h.srchandler.GetOptions()) > 0 { + opts, ok := h.srchandler.GetOptions()[0].(*addhdlrs.Options) + if ok && !opts.Replace { + cd.Resources = nil + cd.Sources = nil + cd.References = nil + } } schema := h.schema