[ 
https://issues.apache.org/jira/browse/SIS-416?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Martin Desruisseaux updated SIS-416:
------------------------------------
    Description: 
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.


  was:
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.

Inconvenient of {{StoreResource}} sub-interface:

* 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 expands the API in a more intrusive way than adding a method.

Inconvenient of method with {{Optional<DataStore>}} return type:

* Most {{Optional}} methods are unusable because of checked exceptions.
* This method make little sense in {{DataStore}} (which is itself a 
{{Resource}}).



> 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
>
> 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.



--
This message was sent by Atlassian Jira
(v8.20.7#820007)

Reply via email to