[
https://issues.apache.org/jira/browse/SIS-416?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Martin Desruisseaux updated SIS-416:
------------------------------------
Fix Version/s: 1.7
(was: 1.6)
> Consider adding StoreResource interface
> ---------------------------------------
>
> Key: SIS-416
> URL: https://issues.apache.org/jira/browse/SIS-416
> Project: Spatial Information Systems
> Issue Type: Task
> Components: Storage
> Affects Versions: 0.8, 1.0, 1.1, 1.2
> Reporter: Martin Desruisseaux
> Assignee: Martin Desruisseaux
> Priority: Major
> Fix For: 1.7
>
>
> The {{org.apache.sis.storage}} package contains a {{Resource}} interface
> which is the root of all resources loaded by a data store ({{FeatureSet}},
> {{Aggregate}}, _etc._). The resources do not tell us which data store created
> them. In some case we need this information, for example in order to fetch
> the parameters used for opening the data store.
> We could add {{getOriginatingStore()}} method in {{Resource}} interface, but
> not all resources are produced by a data store (a resource could be computed
> by a model for example). We could use an {{Optional<DataStore>}} return type,
> but {{Optional}} is not convenient with objects making extensive use of
> checked exceptions, because lambda functions are difficult to use in that
> context.
> A an alternative would be to define the {{getOriginatingStore()}} method in a
> {{StoreResource}} sub-interface, to be implemented only by resources produced
> by data stores. It would be the only method of that interface.
> h1. Use case
> The only use case that has been given up to now is for restoring a resource
> between sessions with the following steps:
> * Save the information provided by {{DataStore#getOpenParameters()}}.
> * Save the {{Resource.getIdentifier()}}.
> With those two information, a resource can be re-fetched later. Those steps
> implies that {{getOriginatingStore()}} should be valid only on resources
> opened _directly_ on the data store. Otherwise (e.g. if the resource is the
> result of a subset), above steps do not provide sufficient information.
> Another use case would be to check if a resource belong to a data store that
> we have just closed (or moved, or whatever). That use case would require a
> different contract: data stores returned even if the resource is the result
> of an operation, and data stores returned as {{Set<DataStore>}} instead of
> {{Optional<DataStore>}}.
> So we have two use cases with contradictory requirements. Only the first use
> case is used in practice at the time of writing this issue.
> h1. Summary of alternatives
> h2. {{StoreResource}} sub-interface
> h3. Advantages
> * Avoid polluting the {{Resource}} API.
> h3. Inconvenient
> * It is very easy to forget to implement it.
> * It is more difficult to implement by wrappers (need to prepare many
> sub-classes for different combination of implemented interfaces).
> * Adding a type inflates the API in a more intrusive way than adding a method.
> * Type safety provided by the use of an interface is not useful in practice
> for this case.
> h2. {{Resource.getOriginatingStore()}} returning {{Optional<DataStore>}}
> h3. Advantages
> * Easier for wrappers to implement.
> * Less risk to forget to implement this method (compiler reminds us).
> h3. Inconvenient
> * Most {{Optional}} methods are unusable because of checked exceptions.
> * This method make little sense in {{DataStore}} (which is itself a
> {{Resource}}).
> h2. {{Resource.getOpenParameters()}} returning
> {{Optional<ParameterValueGroup>}}
> h3. Advantages
> * {{DataStore}} already has this method.
> * Could be used for saving more kind of resources than just the ones produces
> directly by the data store.
> h3. Inconvenient
> * Limit the use case to saving the parameters.
> h2. {{Resource.getSources()}} returning {{Set<Resource>}}
> With callers having to check themselves if the resources are {{DataStore}}
> instances. For finding the root {{DataStore}}, we can iterate recursively in
> the sources until we find a {{DataStore}} with no source (i.e.
> {{getSources()}} return an empty collection).
> h3. Advantages
> * Flexible, addresses more use cases than just the above-cited ones.
> * Familiar pattern for developers.
> h3. Inconvenient
> Still ambiguous, because a {{DataStore}} is also a {{Resource}}. For example
> the CSV data store implements {{FeatureSet}} interface. If we invoke
> {{FeatureSet.query(Query)}} method on it, we get a new {{FeatureSet}}
> instance which has the CSV {{DataStore}} as its sole source. It looks the
> same as a {{FeatureSet}} instance which would be a component of an
> {{Aggregate}}. We do not have a fully reliable way to tell us whether a given
> {{FeatureSet}} is the result of a subset or the component of an aggregate.
> The distinction between the two is relevant if we want to save the parameters
> needed for re-opening the {{FeatureSet}} later.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)