The internal model can be type-safe or not.
We need a way to identify an option from another.
Each option needs a uniquely identifying key object.
This will tell if an option is overridden by another context
or merely duplicated by other values.
For example a named query using different names are not overlapping
but a named query with the same name is replaced by a more specific context.
/**
* Interface required to be returned by the generator classes
* It represents a tuple of the option and the value associated
*
* Option can be of any type, in particular it could be represented as
*
* - an enum value
* - a Class object in particular an annotation class object
* - a String
*
* What is important is that the Option is unique according to
* the `equals()` operation amongst the realm of possible options.
*
* Likewise, Value can be of any type.
*/
publicinterface OptionValueTuple<Option,Value> {
Option getOption();
Value getValue();
}
// most likely an anonymous class in a generator implementation
public class QuorumOptionValueTuple implements OptionValueTuple<OptionEnum,Quorum> {
privatefinalint read;
privatefinalint write;
public QuorumOptionValueTuple(int read, int write) { this.read = read; this.write = write; }
public OptionEnum getOption() { return OptionEnum.QUORUM; }
public Quorum getValue() { returnnew Quorum(read, write); }
}
//an example of possible Option identifier
publicenum OptionEnum {
QUORUM;
}
// the object model representing the QUORUM value
public class Quorum {
privatefinalint read;
privatefinalint write;
public Quorum(int read, int write) { this.read = read; this.write = write }
}
`OptionValueTuple` will be used by Hibernate OGM to collect a map of option / option value and expose that to
the `GridDialect`.
Problem, there is a notion of Option Type and a unique identifier made of option type and some other unique
identifier like in a named query. We uniquely define a named query by it's NamedQuery type and its actual name.
The Option object could be a subtype of `MultiOption`
/**
* Common interfacefor options that can receive multiple values
* like named queries.
* TODO: are generics useful?
*/
public class MultiOption<Type,Id> {
/**
* Class of option, this type can be any type but typically is an
* enum, a Class instance or a String.
*/
abstract Type getType();
/**
* Uniquely identify an option for a given type
*/
abstract Id getUniqueIdentifier();
publicboolean equals(Object that) {
//TODO implementation using getType and getUniqueIdentifier
}
publicint hashCode() {
//TODO implementation using getType and getUniqueIdentifier
}
}
/**
* Example of implementation
*/
public NamedQueryOption extends MultiOption<Class<?>,String> {
privatefinalString queryName;
public NamedQueryOption(String queryName) { this.queryName = queryName; }
Class<?> getType() { return NamedQuery.class; }
String getUniqueIdentifier() { return queryName; }
}
public class NamedQuery {
privateString name;
privateString hql;
...
}
// most likely an anonymous class in a generator implementation
public class NamedQueryOptionValueTuple implements OptionValueTuple<NamedQueryOption, NamedQuery> {
public NamedQueryOptionValueTuple(String name, String hsql) { ... }
public NamedQueryOption getOption() { returnnew NamedQueryOption(name); }
public NamedQuery getValue() { returnnew NamedQuery(name, hql);
}
We could offer the ability to filter options by option or option type to help navigate them.
Wrt overriding, an option is overridden by a closer scope. Same for an option type with the same
unique identifier.
Usage from a GridDialect
We could imagine the following usage
Quorum quorum = (Quorum) context.inGlobalContext().getOption( QUORUM );
List<NamedQuery> queries = (List<NamedQuery>) context.inEntityContext().getOptionByType(NamedQuery.class);
Observations
It seems the model is fairly verbose and I am willing to simplify it if we can. I am especially concerned
about the amount of concepts and classes the designer of an option needs to provide.
Paradoxically, there is not type-safe link between an option and its value besides the `OptionValueTuple`
which is not meant to be used by consumers of options. The `GridDialect` is force to downcast the data
which is not ideal.
I am also concerned about the fact that the set of options is quite dispersed due:
the ability to define the option (or option type) type freely
the fact that some options are specific to a given datastore provider
The design seems to need refinement but I have been working on it for some time now and need a fresh look at it.
Internal model
The internal model can be type-safe or not.
We need a way to identify an option from another.
Each option needs a uniquely identifying key object.
This will tell if an option is overridden by another context
or merely duplicated by other values.
For example a named query using different names are not overlapping
but a named query with the same name is replaced by a more specific context.
/** * Interface required to be returned by the generator classes * It represents a tuple of the option and the value associated * * Option can be of any type, in particular it could be represented as * * - an enum value * - a Class object in particular an annotation class object * - a String * * What is important is that the Option is unique according to * the `equals()` operation amongst the realm of possible options. * * Likewise, Value can be of any type. */ public interface OptionValueTuple<Option,Value> { Option getOption(); Value getValue(); } // most likely an anonymous class in a generator implementation public class QuorumOptionValueTuple implements OptionValueTuple<OptionEnum,Quorum> { private final int read; private final int write; public QuorumOptionValueTuple(int read, int write) { this.read = read; this.write = write; } public OptionEnum getOption() { return OptionEnum.QUORUM; } public Quorum getValue() { return new Quorum(read, write); } } //an example of possible Option identifier public enum OptionEnum { QUORUM; } // the object model representing the QUORUM value public class Quorum { private final int read; private final int write; public Quorum(int read, int write) { this.read = read; this.write = write } }`OptionValueTuple` will be used by Hibernate OGM to collect a map of option / option value and expose that to
the `GridDialect`.
Problem, there is a notion of Option Type and a unique identifier made of option type and some other unique
identifier like in a named query. We uniquely define a named query by it's NamedQuery type and its actual name.
The Option object could be a subtype of `MultiOption`
/** * Common interface for options that can receive multiple values * like named queries. * TODO: are generics useful? */ public class MultiOption<Type,Id> { /** * Class of option, this type can be any type but typically is an * enum, a Class instance or a String. */ abstract Type getType(); /** * Uniquely identify an option for a given type */ abstract Id getUniqueIdentifier(); public boolean equals(Object that) { //TODO implementation using getType and getUniqueIdentifier } public int hashCode() { //TODO implementation using getType and getUniqueIdentifier } } /** * Example of implementation */ public NamedQueryOption extends MultiOption<Class<?>,String> { private final String queryName; public NamedQueryOption(String queryName) { this.queryName = queryName; } Class<?> getType() { return NamedQuery.class; } String getUniqueIdentifier() { return queryName; } } public class NamedQuery { private String name; private String hql; ... } // most likely an anonymous class in a generator implementation public class NamedQueryOptionValueTuple implements OptionValueTuple<NamedQueryOption, NamedQuery> { public NamedQueryOptionValueTuple(String name, String hsql) { ... } public NamedQueryOption getOption() { return new NamedQueryOption(name); } public NamedQuery getValue() { return new NamedQuery(name, hql); }We could offer the ability to filter options by option or option type to help navigate them.
Wrt overriding, an option is overridden by a closer scope. Same for an option type with the same
unique identifier.
Usage from a GridDialect
We could imagine the following usage
Quorum quorum = (Quorum) context.inGlobalContext().getOption( QUORUM ); List<NamedQuery> queries = (List<NamedQuery>) context.inEntityContext().getOptionByType(NamedQuery.class);Observations
It seems the model is fairly verbose and I am willing to simplify it if we can. I am especially concerned
about the amount of concepts and classes the designer of an option needs to provide.
Paradoxically, there is not type-safe link between an option and its value besides the `OptionValueTuple`
which is not meant to be used by consumers of options. The `GridDialect` is force to downcast the data
which is not ideal.
I am also concerned about the fact that the set of options is quite dispersed due:
The design seems to need refinement but I have been working on it for some time now and need a fresh look at it.