I've been thinking about this issue (
http://issues.apache.org/jira/browse/TUSCANY-684) and plan to work on it.
Here are some thoughts

In summary,  we want to be able to hold and access type definitions,
expressed in terms of generated java classes, within the context of a type
scoping artifact.

So first a few invariants about how I think this should work, and then I'd
like to solicit input on some options.

1) We use the tuple of (XXXFactory.class,HelperContext instance) to
get-or-create an instance of the generated XXXFactory class implementation.
For every invocation of the Factory access method with a given
XXXFactory.class,HelperContext pair, the same instance of XXXFactoryImpl is
returned.
2) After invoking the factory access methods, using the TypeHelper instance
associated with the HelperContext instance to create a DataObject in the
namespace of the factory would return an instance of a generated class
3) We deprecate SDOUtil.registerStaticTypes(Class)

So what I'm not yet convinced about is
1) where the interface to the function should sit and
2) where we maintain the state that maps the (XXXFactory.class,HelperContext
instance) tuple to an XXXFactoryImpl instance

In terms of where the function should sit,  I think our choices in the
absence of guidance from the spec is either on SDOUtil or on the generated
classes themselves.  Either of these choices have their upsides and
downsides.

Considering first the housing of the function on SDOUtil.  We might imagine
a method such as

class SDOUtil {
...
  public static Factory getFactory(Class factoryInterface, HelperContext
scope)

}

This method would examine state (wherever that may be housed) to see if a
Factory for the namespace and within the scope already exists, and if so it
would return it,  if not it would create the factory, update the state to
reference the newly created factory, and return the new factory

The issues here are that
1) we don't currently have an abstract "Factory" artifact in our interface
(We have the FactoryBase impl class,  but the most concrete artifact in the
inhertance scheme of things that is currently designed for user consumption
is java.lang.Object)
2) every call to this method is going to require a cast to the specific
XXXFactory before anything can be done

We could avoid both these issues by housing the factory get-or-create method
on a generated artifact, e.g.

interface XXXFactory_InterfaceOfSomeSort {
  public XXXFactory getFactory(HelperContext scope);
}

or class XXXFactory_ClassOfSomeSort {
 static XXXFactory getFactory(HelperContext scope);
}

We could use the interface approach, and use the existing static XXXFactory
INSTANCE as the object which the user can bootstrap Factory creation with (
XXXFactory.INSTANCE.getFactory(scope))  but we are trying to move away from
dependencies on static INSTANCEs (should we be aiming to deprecate the
generated static INSTANCEs in this update?)

We could use the class approach, and use a static method on the exisiting
XXXFactoryImpl (XXXFactoryImpl.getFactory(scope))  but it's ugly requiring
the user to import an impl class

We could introduce a new generated Helper type class per Factory to house
the static method, e.g.

public class XXXFactoryHelper {
  public static XXXFactory getFactory(HelperContext scope)
}

so that the user's code would look fairly clean
XXXFactory xFac = XXXFactoryHelper.getFactory(scope);

Of the generated artifact approaches, I like the last example best.

We could use both approaches, and give the user the choice.  The SDOUtil
method would just delegate to the generated artifact method.

The second issue is where to house the state that holds the mapping between
the tuple and the factory instance.  It seems to me that there are two
reasonable choices

1) in the HelperContext instance, as a hashmap from namespace to Factory
instance, or
2) in static state associated with the generated classes, as a hashmap from
HelperContext instance to XXXFactory

I favour (1) quite strongly,  as I see the HelperContext as an instrument of
placing control of concurrency and class loader issues firmly in the hands
of the user.

Assuming (1) it may be worth giving the implementation issue of exacly where
with the HelperContext and it's associated helpers this state is maintained
(or course if we ensure the implementation doesn't leak then we have
flexibility to change this in the light of spec updates)

It might seem natural to put it in the TypeHelperImpl,  but TypeHelper is a
spec artifact that ought to stay language neutral, so clouding the impl with
Java considerations is not perhaps a good move.  We could try to second
guess the spec and create a JavaHelperImpl to house the state,  but that
would be its only function currently, so my thoughts are that I will house
the state directly in the HelperContextImpl for now,  and move it if and
when it logically becomes part of a specified artifact.

I'll give this a while for some feedback, and in the meantime I'm going to
explore / prototype the the combination of
SDOUtil.getFactory(Class, HelperContext) with housing the Factory instance
mappings in the HelperContext.  This would seem an OK approach,  since I
think little or no effort will wasted if anyone comes up with a convincing
argument that we should take alternative elements of my proposition,  or
something completely different.

Regards, Kelvin.

Reply via email to