On 10/26/2011 10:36 PM, Matt Benson wrote:
On Wed, Oct 26, 2011 at 3:42 PM, Simone Tripodi
<simonetrip...@apache.org>  wrote:
Hi Adrian!
nice to see you involved here!

So, I took few time to reorganize my ideas and I would like to discuss
with you how to make a new [convert] component,.

For what I can see, the bigger part of the codebase has been kindly
borrowed from BeanUtils - which is fine - but, like always, I am
convinced we can give our users new experiences of using commons APIs.
Please take in consideration that I didn't gave any try and the
following below are random thoughts I had while driving to come back
home, so apologize in advance if something wouldn't sound correct.

  * The first modification I'm proposing is about managing types
automagically - taking a look at GoogleGuice's TypeLyteral[1] it is
possible to understand that is possible to do some magic with Java
Generics, that would allow discovery types at runtime.
That would mean that converter types can be discovered at runtime -
without the users have to specify them - and that object type under
conversion can be discovered as well.
Guice code is licensed under ASL2.0 so parts could be extracted for our needs.
If I'm understanding the next part correctly you would recommend we
use something like what TypeLiteral does in our implementation more so
than the interface.  If so I'd say we should just use it directly and
manage it with mvn-shade.

  * The second proposal concerns about fluent APIs. Taking advantage
fromm the previous point, the existing pattern

    getConverter( Class<?>, Class<?>  ).convert( Object );

could be replaced by a fluent one:

  <S, T>  T  convert( S ).to( Class<T>  )

Maybe, but one issue that comes up with conversion is Locale.  For
this reason Morph defines transformation APIs of varying complexity:
a set with Locale, and a simplified set without Locale that calls the
"full" API using the default Locale.  Another issue you run into when
doing non-trivial conversions is (extended) reflection.  For this
reason Morph defines a set of *Reflector interfaces, etc.  I would
like for the next-generation object conversion API to include the
notion of a context which would include an ELContext whose ELResolver
could be used to handle reflection-related duties, as well as storing
the Locale.  In fact given the API of ELContext that could just be the
root host of the context and any further information we might want to
manage could be accessed via its putContext/getContext API.  For
example, it could occasionally be handy when doing (arbitrarily
deeply) nested conversions/copies to have a stack of contextual
information available.  Additionally handling conversions in this
recursive-descent fashion is probably the most elegant way to handle
nested conversions, which is presumably why the EL APIs are structured
this way.  I think there is inherent value in sharing structural
similarities with well-known specifications, as well, from an adoption
perspective.  Note that I think all this could be managed fairly
easily with the right fluent APIs, so this isn't necessarily at odds
with what you're looking for.  Just the implementation of a converter
would need to take the context into account.  Even this could be
avoided for simple cases by providing an abstract class with the
simplified API, again similarly to what Morph does.  Finally, the
presence of the ELContext would make it possible to defer simple
conversions to its "coercion" functionality.

  * The third proposal is about the loaders: IMHO the auto-loaders are
not so elegant and a ServiceLoader pattern would be more canonical -
and enough.
Anyway I like the public API to register converters - ServiceProvider
should not be a constraint - and we could modify them in a more fluent
way:

   <S, T>  convert( Class<S>  ).to( Class<T>  ).withConverter(
Converter<? extends S, ? extends T>  )
This approach to the fluent API feels backward and of less value to
me.  I envision some central point-of-access class providing static
factory methods for a context, which can be modified, then .<S>
convert(S).<T>to(Class<T>) called.  The central class would also
provide a convenience .<S>  convert(S) method that bridged directly to
a default context.  I am still conflicted over whether the context
should extend or encapsulate the ELContext.  My head says the latter,
but my gut says the former.  :/

So, what are your opinions/roadmaps about this component?
@Adrian:  If my ideas are too far off the current [convert] codebase
for you, I am happy to work in a separate sandbox for the time being.

Do note that I joined the Morph team almost 5 years ago, and
contributed to Dozer before that--I have had a long time to think
about object transformation.

I am not opposed to what you are suggesting, but I would prefer if it was designed in such a way that it is an option. My original thinking was that a library or application that uses Common Convert would have its own facade class that does what you describe.

-Adrian


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to