Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

IdAS Update Proposals Distillation

This is similar to other options, but let's start fresh. Ignore the topic of transaction semantics until we come to that.

Specifying updates

Like some other proposals, we would remove the build<element> methods (those methods that build subjects, attributes, metadata, and property values) from IContext. We would also remove IContext.updateSubject. We would replace this way of doing things as follows:

Each IdAS element would have methods on it like add and remove which allow a caller to update (add, remove, modify) a contained element.

Arguments to these methods are:

  1. an identifier (used to build a new instance of the contained element)
  2. (optionally) an object from which new sub element is built.
    1. This one can be debated (or placed in the optional section), it only adds a supposed level of convenience.

Ignoring the debatable argument above, these methods could look like the following:

/**
 * Creates a new Digital Subject for this Context.<br>
 * This call is typically followed by one or more calls to 
 * {@link IDigitalSubject#addAttribute}, {@link IDigitalSubject#addMetadata}
 * on the returned IDigitalSubject
 * Note: This operation is only applied to any backing data 
 * store after applyUpdates() is called on the returned IDigitalSubject
 * @param type The URI specifying the type of Digital Subject being created
 * @param subjectID May be null.  When specified, uniquely names the subject within 
 *                  this Context.  When null, indicates that the caller plans to 
 *                  later add an attribute or attributes which will be used to 
 *                  construct the unique subject ID
 * @throws <someException> when the type is invalid
 * @throws <someException> when the subjectID is invalid
 * @throws <someException> when the subjectID is known to already exist
 */
IDigitalSubject IContext.addSubject(URI type, String subjectID)
/**
 * Removes this Digital Subject from its Context.
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on this 
 * IDigitalSubject instance. <br>
 * Note: It is invalid to call subsequent update operations on this 
 * IDigitalSubject instance or on any elements held by this Digital 
 * Subject or by any of its sub-elements.
 * 
 * @throws <someException>
 */
void IDigitalSubject.remove()
/**
 * Creates a new Attribute for this container of attributes (typically IDigitalSubject).
 * This call is typically followed by one or more calls to 
 * {@link IProperty#addValue}, {@link IProperty#addSimpleValue}, 
 * {@link IProperty#addComplexValue}, (@link IHasMetadata#addMetadata} on
 * the returned IAttribute
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @param type The URI specifying the type of Attribute being created
 * @throws <someException>
 */
IAttribute IHasAttributes.addAttribute(URI type)
/**
 * Creates a new Metadata element for this container of metadata.
 * This call is typically followed by one or more calls to 
 * {@link IProperty#addValue}, {@link IProperty#addSimpleValue}, 
 * {@link IProperty#addComplexValue} on the returned IMetadata
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @param type The URI specifying the type of Metadata being created
 * @throws <someException>
 * todo: remove IHasMetadata from IContext*
 */
IMetadata IHasMetadata.addMetadata(URI type)
/**
 * Creates a new Property for this container of properties.
 * This call is typically followed by one or more calls to 
 * {@link IProperty#addValue}, {@link IProperty#addSimpleValue}, 
 * {@link IProperty#addComplexValue} on the returned IProperty
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @param type The URI specifying the type of Property being created
 * @throws <someException>
 */
IProperty IHasProperties.addProperty(URI type)
/**
 * Removes this property from its container
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @throws <someException>
 */
void IProperty.remove()
/**
 * Creates a new value for this property.  This method is useful
 * when the caller doesn't know whether the URI specified in the 
 * type param will build an ISimpleValue or IComplexValue.  Otherwise
 * callers will typically call {@link IProperty#addSimpleValue(URI, Object}
 * or {@link IProperty#addComplexValue(URI}
 * This call is typically followed by a call to {@link IPropertyValue#isSimple}
 * on the returned IPropertyValue.
 * When found to be an ISimpleValue, {@link ISimpleValue.setData} is typically 
 * called on the returned IPropertyValue (cast as an ISimpleValue).
 * When found to be an IComplexValue, one typically calls 
 * {@link IHasProperties#addProperty} on the returned IPropertyValue 
 * (cast as an IComplexValue or IHasProperties).
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @param type The URI specifying the type of Value being created
 * @throws <someException>
 */
IPropertyValue IProperty.addValue(URI type)
/**
 * Creates a new simple value for this property. 
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @param type The URI specifying the type of Value being created
 * @param data The data of the property value
 * @throws <someException>
 */
ISimpleValue IProperty.addSimpleValue(URI type, Object data)
/**
 * Creates a new complex value for this property. 
 * This call is typically followed by one or more calls to 
 * {@link IHasProperties#addProperty} on the returned IComplexValue.
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @param type The URI specifying the type of Property being created
 * @throws <someException>
 */
IComplexValue IProperty.addComplexValue(URI type)
/**
 * Removes this value from its IProperty
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @throws <someException>
 */
void IPropertyValue.remove()
/**
 * Sets the data for this simple value.
 * This is typically called after calling {@link IProperty.addValue(URI type)}
 * Note: This operation is only applied to any backing data store after
 * IDigitalSubject.applyUpdates() is called on the containing 
 * IDigitalSubject instance.
 * @param data The data of the property value
 * @throws <someException>
 */
void ISimpleValue.setData(Object data)

Application of updates

I think so far, everyone likes placing the update operations on the specific IdAS elements. Where it gets messy is the point at which the update is applied to a context's backing store. While some CP's could apply updates as each update operation (like add or remove) is called, other CP's cannot--as doing so would temporarily put objects into an invalid state.

Obviously for the second type of CP above, we need to provide a way for the caller to submit a set of updates to the CP. One way of doing this is to do these two things:

  1. Provide a way of saying applyUpdates at some point to indicate that the caller believes things are in a valid state. I think we all agree on this basic need.
  2. State that update operations are not applied to a backing store until the caller indicates that he believes things are in a valid state.
    1. See Optional Functionality in regards to other ideas on this.

Placement of the applyUpdates method

There are a number of interfaces to which we could add such a method. Option 3 proposed to add it to IContext. Let's explore two alternatives:

  1. Place it only on IDigitalSubject (IDigitalSubject.applyUpdates(<maybe some args>)). In this case, it would apply all pending updates that have been made to that subject (including the event of that subject being added to a context).
  2. Place it on all elements of a context including IContext, IDigitalSubject, IAttribute, IMetadata, IPropertyValue, etc. In this case, it would either:
    1. apply all pending updates that have been made to that element, or
    2. apply all pending updates that have been made to that element and all updates made to all contained elements.

I prefer the first alternative as it seems simpler. 2.1 is unworkable in my mind because in fact, it's no different from not having the method at all. The first alternative could look like this:

/**
 * Applies all update operations which have been called on this Digital Subject 
 * and called on any element held by this Digital Subject 
 * (including metadata, attributes, attribute metadata and it's value(s), and attribute values) 
 * to a backing data store.  These updates are applied atomically when possible, but may not be 
 * applied atomically by Context Providers which do not support this.
 * Update operations which will be applied are any of the following:<br>
 * todo: make this list consistent with list methods above
 * IContext.addSubject(URI, String) (which resulted in the creation of this Digital Subject <br>
 * IHasAttributes.addAttribute(URI) <br>
 * IHasMetadata.addMetadata(URI) <br>
 * IHasProperties.addProperty(URI) <br>
 * IProperty.remove() <br>
 * IProperty.addValue(URI) <br>
 * IProperty.addSimpleValue(URI, Object) <br>
 * IProperty.addComplexValue(URI) <br>
 * IPropertyValue.remove() <br>
 * ISimpleValue.setData(Object) <br>
 * On a successful return, all updates which have been performed on this Digital Subject 
 * or on any contained elements are said to be fully applied to the Context.  
 * Subsequent update operations must be followed by another call to applyUpdates.
 * On error (when an exception is thrown), the updates are said to not yet be applied
 * to the Context.  In this case, the caller may attempt to remedy the issue which 
 * caused the call to applyUpdates by performing further update operations followed
 * by another call to applyUpdates().  The caller may also discard the reference to 
 * this IDigitalSubject in which case the updates will never be applied to the Context.
 * In other words, when this fails, the caller can either attempt to fix the problem and
 * retry, or give up and start over with another instance of IDigitalSubject.
 * @throws <someException> when all operations cannot be applied.
 */
void IDigitalSubject.applyUpdates()

Transaction Semantics

Nothing so far has been said about transactional integrity of the updates as grouped by the applyUpdates method. We previously agreed in a previous F2F that all operations are atomic, but this seems to be a special case. The reason we need applyUpdates is primarily so the consumer can call it when he believes the updates to this point represent a valid state. The intent was not to introduce multi-operation transaction support.

I propose we state that CP's should treat the application of the updates as an atomic operation, but are not required to if they can't.

I'd like to delay the topic of general transaction support for its own discussion.

Optional functionality

I believe applying the above (after agreeing on the placement of applyUpdates will solve the problem stated. So, here are the optional characteristics I think I've heard people ask for:

Option to apply updates when update operations are called

Some different proposals have emerged here:

  1. Add an argument to each update operation which specifies whether the application should be immediate or delayed until applyUpdates is called
  2. Add a method that lets the user specify the behavior for subsequent calls to update (like a switch that can toggled)
  3. State that the user has no control of when application happens, the CP will decide when to apply.
    1. This is subtly different than the previous two ideas. The previous two ideas imply that when updates are being applied as the operations are called, there's no reason for the caller to later call applyUpdates. This idea would have the caller always call applyUpdates, but not know when exactly the updates were actually applied.

I prefer either of the first two, or tabling this option altogether.

Option to also place applyUpdates at the IContext level

At one point, when we were going to force applyUpdates to be atomic in nature, David Kuehr-McLaren requested that we also put an applyUpdates on IContext. His request:

  • I also have the need to be able to update multiple IDigitalSubjects as an atomic operation. One use case for this is the ability to create a person and add them to a group as a single operation. Would applyUpdate on IContext allow atomic operations involving multiple IDigitalSubjects?

Back to the top