Documentation ¶
Overview ¶
This package contains SCIM property definitions and its respective implementations defined in the SCIM specification. Various mechanisms to access data structure and react to local data changes are also part of the package.
Index ¶
- func SubscriberFactory() *subscriberFactory
- func Visit(property Property, visitor Visitor) error
- type AutoCompactSubscriber
- type CoCapable
- type ComplexStateSummarySubscriber
- type EqCapable
- type Event
- type EventType
- type Events
- type EwCapable
- type ExclusivePrimarySubscriber
- type GeCapable
- type GtCapable
- type LeCapable
- type LtCapable
- type Navigator
- type PrCapable
- type Property
- func NewBinary(attr *spec.Attribute) Property
- func NewBinaryOf(attr *spec.Attribute, value string) Property
- func NewBoolean(attr *spec.Attribute) Property
- func NewBooleanOf(attr *spec.Attribute, value bool) Property
- func NewComplex(attr *spec.Attribute) Property
- func NewComplexOf(attr *spec.Attribute, value map[string]interface{}) Property
- func NewDateTime(attr *spec.Attribute) Property
- func NewDateTimeOf(attr *spec.Attribute, value string) Property
- func NewDecimal(attr *spec.Attribute) Property
- func NewDecimalOf(attr *spec.Attribute, value float64) Property
- func NewInteger(attr *spec.Attribute) Property
- func NewIntegerOf(attr *spec.Attribute, value int64) Property
- func NewMulti(attr *spec.Attribute) Property
- func NewMultiOf(attr *spec.Attribute, value []interface{}) Property
- func NewProperty(attr *spec.Attribute) Property
- func NewReference(attr *spec.Attribute) Property
- func NewReferenceOf(attr *spec.Attribute, value string) Property
- func NewString(attr *spec.Attribute) Property
- func NewStringOf(attr *spec.Attribute, value string) Property
- type Resource
- func (r *Resource) Clone() *Resource
- func (r *Resource) Hash() uint64
- func (r *Resource) IdOrEmpty() string
- func (r *Resource) MainSchemaId() string
- func (r *Resource) MetaLocationOrEmpty() string
- func (r *Resource) MetaVersionOrEmpty() string
- func (r *Resource) Navigator() Navigator
- func (r *Resource) ResourceType() *spec.ResourceType
- func (r *Resource) RootAttribute() *spec.Attribute
- func (r *Resource) RootProperty() Property
- func (r *Resource) Visit(visitor Visitor) error
- type SchemaSyncSubscriber
- type Subscriber
- type SubscriberFactoryFunc
- type SwCapable
- type Visitor
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SubscriberFactory ¶
func SubscriberFactory() *subscriberFactory
Return the subscriber factory to Register and Create subscribers using annotations.
func Visit ¶
Visit is the entry point to visit a property in a depth-first-search fashion.
Example ¶
getVisitor := func() Visitor { // type ExampleVisitor struct {} // // func (v *ExampleVisitor) ShouldVisit(_ Property) bool { // return true // } // // func (v *ExampleVisitor) Visit(property Property) error { // println(property.Raw()) // return nil // } // // func (v *ExampleVisitor) BeginChildren(container Property) { // println("entering", container.Attribute().Path()) // } // // func (v *ExampleVisitor) EndChildren(container Property) { // println("exiting", container.Attribute().Path()) // } // assuming it returns the above ExampleVisitor return nil } v := getVisitor() getProperty := func() Property { // Assuming a property structure of: // { // "id": "foobar", // "name": { // "givenName": "David", // "familyName": "Q" // } // } // assuming it returns the above property return nil } p := getProperty() _ = Visit(p, v) // should print: // // foobar // map[string]interface{}{"givenName": "David", "familyName": "Q"} // entering name // David // Q // exiting name
Output:
Types ¶
type AutoCompactSubscriber ¶
type AutoCompactSubscriber struct{}
AutoCompactSubscriber automatically compacts the multiValued property.
It is mounted by @AutoCompact annotation onto a multiValued property. If the mounted property is not multiValued, this subscriber does nothing.
The subscriber reacts to unassigned events from its elements and invokes the hidden Compact API on the multiValued property.
type CoCapable ¶
type CoCapable interface { // Contains return true if the property's value contains the given value. // If the given value is nil, always return false. Contains(value string) bool }
CoCapable defines capability to perform 'co' operations. It should be implemented by capable Property implementations.
type ComplexStateSummarySubscriber ¶
type ComplexStateSummarySubscriber struct {
// contains filtered or unexported fields
}
ComplexStateSummarySubscriber summarizes the state changes of the sub properties of a complex property and generate new event to describe the inferred state change on the complex property.
It is mounted by @StateSummary annotation onto a complex property. If the mounted property is not complex, this subscriber does nothing.
The subscriber reacts to state change events from its sub properties and computes a new assigned state for the complex property. The new state is compared to an old cached assigned state in order to determine state change for the complex property. It also reacts to direct state changes on the complex property itself, in which case, the subscriber simply updates the state without generating new events.
type EqCapable ¶
type EqCapable interface { // EqualsTo return true if the property's value is equal to the given value. // If the given value is nil, always return false. EqualsTo(value interface{}) bool }
EqCapable defines the capability to perform 'eq' operations, and by logic, 'ne' operations. It should be implemented by capable Property implementations.
type Event ¶
type Event struct {
// contains filtered or unexported fields
}
A single modification event.
func (Event) PreModData ¶
func (e Event) PreModData() interface{}
PreModData optionally returns the Source's data before the modification. Note PreModData is not always available, hence should not be relied upon.
type EventType ¶
type EventType int
Type of an event
const ( // Event that new value has been assigned to the property. // The event entails that the property is now in an "assigned" state, such that // calling IsUnassigned shall return false. It is only emitted when value introduced // to the property is different than the previous value, otherwise, no event would be // emitted. EventAssigned EventType // Event that property value was deleted and now is an "unassigned" state. Calling // IsUnassigned shall return true. It is only emitted that value was deleted from property // when it was in an "assigned" state, otherwise, no event would be emitted. EventUnassigned )
Type of modification events
type Events ¶
type Events struct {
// contains filtered or unexported fields
}
Events is the package of one or more Event. While a single modification call emits a single Event, the emitted event is wrapped in the Events package and passed along the trace stack for subscriber processing. Subscriber may modify or append to the events in this package, hence the necessity for this structure.
type EwCapable ¶
type EwCapable interface { // EndsWith return true if the property's value ends with the given value. // If the given value is nil, always return false. EndsWith(value string) bool }
EwCapable defines capability to perform 'ew' operations. It should be implemented by capable Property implementations.
type ExclusivePrimarySubscriber ¶
type ExclusivePrimarySubscriber struct{}
ExclusivePrimarySubscriber automatically turns off the true-valued primary sub property when another primary sub property is set to true.
It is mounted by @ExclusivePrimary annotation onto the a multiValued complex property whose sub property contains a boolean property which is annotated @Primary. This boolean property is referred to as the primary property.
The subscriber reacts to assigned events from the primary property. If the event reports a primary property has a new value of true, this subscriber goes through all primary properties and turn off the old true value. The result is that at most one primary property will have the value of true.
type GeCapable ¶
type GeCapable interface { // GreaterThanOrEqualTo return true if the property's value is greater than or equal to the given value. // If the given value is nil, always return false. GreaterThanOrEqualTo(value interface{}) bool }
GeCapable defines capability to perform 'ge' operations. It should be implemented by capable Property implementations.
type GtCapable ¶
type GtCapable interface { // GreaterThan return true if the property's value is greater than the given value. // If the given value is nil, always return false. GreaterThan(value interface{}) bool }
GtCapable defines capability to perform 'gt' operations. It should be implemented by capable Property implementations.
type LeCapable ¶
type LeCapable interface { // LessThanOrEqualTo return true if the property's value is greater than or equal to the given value. // If the given value is nil, always return false. LessThanOrEqualTo(value interface{}) bool }
LeCapable defines capability to perform 'le' operations. It should be implemented by capable Property implementations.
type LtCapable ¶
type LtCapable interface { // LessThan return true if the property's value is greater than the given value. // If the given value is nil, always return false. LessThan(value interface{}) bool }
LtCapable defines capability to perform 'lt' operations. It should be implemented by capable Property implementations.
type Navigator ¶
type Navigator interface { // during the navigation had generated an error, further steps will become // no op and the original error is reflected here. Error() error HasError() bool ClearError() // currently focused. These properties, excluding the current one, can be // refocused by calling Retract, one at a time in the reversed order that // were focused. The minimum depth is one. Depth() int Source() Property Current() Property // this navigator was created with cannot be retracted Retract() Navigator Dot(name string) Navigator At(index int) Navigator Where(criteria func(child Property) bool) Navigator Add(value interface{}) Navigator Replace(value interface{}) Navigator Delete() Navigator // The method returns any error generated previously or generated by any of the callbacks. ForEachChild(callback func(index int, child Property) error) error }
Navigator is a controlled mechanism to traverse the Resource/Property data structure. It should be used in cases where the caller has knowledge of what to access. For example, when de-serializing JSON into a Resource, caller has knowledge of the JSON structure, therefore knows what to access in the Resource structure.
The Navigator exists for two purposes: First, to maintain a call stack of the traversal trace, enabling modification events to be propagated along the trace, all the way to the root property, and notify subscribers on every level. Without such call stack, such things will have to resort to runtime reflection, which is hard to get right or maintain. Second, as a frequently used feature, the Navigator promotes fluent API by returning the instance for the majority of the accessor methods, making the code easier to read in general.
Because the Navigator does not return error on every error-able operation, implementation will mostly be stateful. Callers should call Error or HasError to check if the Navigator is currently in the error state, after performing one or possibly several chained operations fluently.
The call stack can be advanced by calling Dot, At and Where methods. Which methods to call depends on the context. The call stack can be retracted by calling Retract. The top and the bottom item on the stack can be queried by calling Current and Source. The stack depth is available via Depth.
func Navigate ¶
Navigate returns a navigator that allows caller to freely navigate the property structure and maintains the navigation history to enable retraction at any time. The navigator also exposes delegate methods to modify the property, and propagate modification events to upstream properties.
type PrCapable ¶
type PrCapable interface { // Present return true if the property's value is present. Presence is defined to be non-nil and non-empty. Present() bool }
PrCapable defines capability to perform 'pr' operations. It should be implemented by capable Property implementations.
type Property ¶
type Property interface { // Attribute always returns a non-nil attribute to describe this property. Attribute() *spec.Attribute // Raw return the property's value in Golang's native type. The type correspondence are: // SCIM string <-> Go string // SCIM integer <-> Go int64 // SCIM decimal <-> Go float64 // SCIM boolean <-> Go bool // SCIM dateTime <-> Go string // SCIM reference <-> Go string // SCIM binary <-> Go string // SCIM complex <-> Go map[string]interface{} // SCIM multiValued <-> Go []interface{} // Property implementations are obliged to return in these types, or return a nil when unassigned. However, // implementations are not obliged to represent data in these types internally. Raw() interface{} // IsUnassigned return true if this property is unassigned. Unassigned is defined to be nil for singular non-complex // typed properties; empty for multiValued properties; and complex properties are unassigned if and only // if all its containing sub properties are unassigned. IsUnassigned() bool // Dirty returns true if any of Add/Replace/Delete method was ever called. // This method is necessary to distinguish between a naturally unassigned state and a deleted unassigned state. // When a property is first constructed, it has no value, and hence lies in an unassigned state. However, this // shall not be considered the same with a property returning to an unassigned state after having its value deleted. // Such difference is important as the SCIM specification mandates that user may override the server generated // default value for a readWrite property by explicitly providing "null" or "[]" (in case of multiValued) in the // JSON payload. In such situations, value generators should back off when an unassigned property is also dirty. Dirty() bool // Hash returns the hash value of this property's value. This will be helpful in comparing two properties. // Unassigned values shall return a hash of 0 (zero). Although this will create a potential hash // collision, we avoid this problem by checking the unassigned case first before comparing hashes. Hash() uint64 // Matches return true if the two properties match each other. Properties match if and only if // their attributes match and their values are comparable according to the attribute. // For properties carrying singular non-complex attributes, attributes and values are compared. // For complex properties, two complex properties match if and only if all their identity sub properties match. // For multiValued properties, match only happens when they have the same number of element properties // and the element properties all match correspondingly. // Two unassigned properties with the same attribute matches each other. Matches(another Property) bool // Clone return an exact clone of the property. The cloned property may share the same instance of attribute and // subscribers, but must retain individual copies of their values. Clone() Property // Add a value to the property and emit an event describing the change. // If the value already exists, no change will be made and the emitted event is nil. Otherwise, the value will // be added to the underlying data structure and mark the value dirty. For simple properties, calling this // method equates to calling Replace. Add(value interface{}) (*Event, error) // Replace value of this property and emit an event describing the change. // If the value equals to the current value, no change will be made and the emitted event is nil. Otherwise, // the underlying value will be replaced. Providing a nil value equates to calling Delete. Replace(value interface{}) (*Event, error) // Delete value from this property and emit an event describing the change. // If the property is already unassigned, deleting it again has no effect. Delete() (*Event, error) // Notify all subscribers of this property of the events. Notify(events *Events) error // CountChildren returns the number of children properties. Children properties are sub properties for complex // properties and element properties for multiValued properties. Other properties have no children. CountChildren() int // ForEachChild iterates all children properties and invoke callback function. ForEachChild(callback func(index int, child Property) error) error // FindChild returns the first children property that satisfies the criteria, or nil if none satisfies. FindChild(criteria func(child Property) bool) Property // ChildAtIndex returns the children property at given index. The type of index vary across implementations. ChildAtIndex(index interface{}) (Property, error) }
Property holds a piece of data and is describe by an Attribute. The data requirement of the property is described by an enclosing attribute returned by the Attribute method. The enclosed data may be accessed via Raw and IsUnassigned method, and may be modified by Add, Replace and Delete method.
A Property may enclose other properties. Such property is known to be a container property. Default cases of container property are the singleValued complex property and the multiValued property, as defined in SCIM. A non-container property must return 0 to CountChildren and is generally indifferent to CountChildren, ForEachChild, FindChild and ChildAtIndex methods.
func NewBinaryOf ¶
NewBinaryOf creates a new binary property of given value associated with attribute.
func NewBoolean ¶
NewBoolean creates a new boolean property associated with attribute.
func NewBooleanOf ¶
NewBooleanOf creates a new boolean property of given value associated with attribute.
func NewComplex ¶
NewComplex creates a new complex property associated with attribute. All sub attributes are created.
func NewComplexOf ¶
NewComplexOf creates a new complex property of given value associated with attribute.
func NewDateTime ¶
NewDateTime creates a new dateTime property associated with attribute.
func NewDateTimeOf ¶
NewDateTimeOf creates a new dateTime property of given value associated with attribute.
func NewDecimal ¶
NewDecimal creates a new decimal property associated with attribute.
func NewDecimalOf ¶
NewDecimalOf creates a new decimal property of given value associated with attribute.
func NewInteger ¶
NewInteger creates a new integer property associated with attribute.
func NewIntegerOf ¶
NewIntegerOf creates a new integer property of given value associated with attribute.
func NewMulti ¶
NewMulti creates a new multiValued property associated with attribute. All sub attributes are created.
func NewMultiOf ¶
NewMultiOf creates a new multiValued property of given value associated with attribute.
func NewProperty ¶
NewProperty creates a new property of any legal SCIM type
func NewReference ¶
NewReference creates a new reference property associated with attribute.
func NewReferenceOf ¶
NewReferenceOf creates a new reference property of given value associated with attribute.
type Resource ¶
type Resource struct {
// contains filtered or unexported fields
}
Resource represents a SCIM resource. It is a wrapper around the root Property.
func NewResource ¶
func NewResource(resourceType *spec.ResourceType) *Resource
NewResource creates a resource prototype of the attributes defined in the resource type, along with the core SCIM attributes.
func (*Resource) Clone ¶
Return a clone of this resource. The clone will contain properties that share the same instance of attribute and subscribers with the original property before the clone, but retain separate instance of values.
func (*Resource) Hash ¶
Hash returns the hash of this resource, which is same hash of the root property.
func (*Resource) IdOrEmpty ¶
IdOrEmpty returns the id of the resource, defined in the core schema. If in any case the id is not available, (i.e. unassigned, wrong type), empty string is returned.
func (*Resource) MainSchemaId ¶
MainSchemaId returns the id of the resource type's main schema.
func (*Resource) MetaLocationOrEmpty ¶
MetaLocationOrEmpty returns meta.location value of the resource, defined in the core schema. If in any case, the meta.location value is not available (i.e. unassigned, wrong type), empty string is returned.
func (*Resource) MetaVersionOrEmpty ¶
MetaVersionOrEmpty returns meta.version value of the resource, defined in the core schema. If in any case, the meta.version value is not available (i.e. unassigned, wrong type), empty string is returned.
func (*Resource) ResourceType ¶
func (r *Resource) ResourceType() *spec.ResourceType
ResourceType returns the resource type of this resource
func (*Resource) RootAttribute ¶
RootAttribute returns the attribute of the root property
func (*Resource) RootProperty ¶
RootProperty returns the root property
type SchemaSyncSubscriber ¶
type SchemaSyncSubscriber struct{}
SchemaSyncSubscriber automatically synchronizes the schema property with respect to data changes in the resource.
It is mounted by @SyncSchema annotation onto the root of the property whose attribute is annotated with @Root. If not mounted onto @Root, this subscriber does nothing.
The subscriber reacts to state change events from the root property of schema extension attributes. In other words, it reacts to events whose source attribute is annotated with @StateSummary and @SchemaExtensionRoot. It adds the schema extension id to schemas property on assigned events; and removes the schema extension id from schemas property on unassigned events.
This subscriber does not attempt to compact the schemas property after element removal. This should be handled by AutoCompactSubscriber.
type Subscriber ¶
type Subscriber interface { // Be notified and react to the a series of events. Subscriber is allowed to modify the events list in order to // affect downstream subscribers. Notify(publisher Property, events *Events) error }
Subscriber attaches to Property and gets notified various state change events via Notify method.
There is no explicit way of attaching to Property. All Subscriber implementations are automatically loaded onto Property via the annotation mechanism. A Subscriber can Register itself with the SubscriberFactory via an annotation. When a Property is being created, it will check if one or more of its attribute annotations are associated with Subscriber and ask SubscriberFactory to create an instance of Subscriber and attach the instance to itself.
Implementations can choose to be either stateful or stateless. It is more memory efficient to create a single instance of stateless Subscriber. Yet, stateful subscribers might be more powerful as it allows user to specify parameters with the annotation, which gets passed in during initialization in the SubscriberFactory.
type SubscriberFactoryFunc ¶
type SubscriberFactoryFunc func(publisher Property, params map[string]interface{}) Subscriber
Constructor function to initialize a Subscriber instance.
publisher is the property that is creating the Subscriber, and also what the Subscriber will eventually subscribe to. params is the parameter specified with the annotation that was associated with the Subscriber type, it might be useful when customizing Subscribers during initialization.
Stateless Subscriber implementation may choose to return the same instance.
type SwCapable ¶
type SwCapable interface { // StartsWith return true if the property's value starts with the given value. // If the given value is nil, always return false. StartsWith(value string) bool }
SwCapable defines capability to perform 'sw' operations. It should be implemented by capable Property implementations.
type Visitor ¶
type Visitor interface { // Returns true if property should be visited; if false, the property will not be visited. ShouldVisit(property Property) bool // Visit the property, only when ShouldVisit returns true. If this method returns non-nil error, // the rest of the traversal will be aborted. Visit(property Property) error // Invoked when the children properties of a container property is about to be visited. The containing // property is supplied as an argument to provide context information. The container property itself, // however, has already been invoked on ShouldVisit and/or Visit. BeginChildren(container Property) // Invoked when the children properties of a container property has finished. The containing property // is supplied as a context argument. EndChildren(container Property) }
Visitor defines behaviour for implementations to react to a passive Property structure traversal. It shall be used in cases where caller does not have knowledge of resource structure and has to rely on a spontaneous DFS traversal. By implementing this interface, caller will have some control over whether a property should be visited and be notified for entering and exiting container Property.