From: Martin D. <mar...@no...> - 2005-03-07 10:54:35
|
Jody Garnett a =E9crit : > So here is the *only* point I need to make sure of. I need to ensure=20 > that ServiceRegistry.setOrdering( ... ) is not GLOBAL. And is indeed=20 > limited to a single use (say for a single instnaceof of a FactoryFinder= =20 > used by a DataStore). 'setOrdering(...)' applies to a particular instance of ServiceRegistry. In order to make it non-global for CRS's FactoryFinder (for example), we=20 need to change all static methods into member methods, so that each=20 FactoryFinder instance uses its own ServiceRegistry instance. > Given CarFactory and WheelFactory > - WheelFactoryFinder > - CarFactory (makes use of a WheelFactoryFinder to locate a WheelFactor= y) >=20 > Either: > 1) User create a CarFactoryFinder > 2) User calls carFactoryFinder.setOrdering( "european", "japanese" = ) > 3) User creates a hints map > 3.1) User set a wheel ordering - hints.put( WHEEL_ORDERING, {"square"= ,"triangle") ) > 4) User calls carFactoryFinder.create( Color.BLUE, hints ) > 4.1) europeanCarFactory calls create a wheelFactoryFinder > 4.2) europeanCarFactory calls wheelFactoryFinder.setOrdering( hints.g= et( WHEEL_ORDERING ) ) > 4.3) europeanCarFactory calls wheelFactoryFinder.create() > 4.3.1) triangleWheel.create() is called 4 times > 4.4) europeanCarFactory creates a car with the 4 wheels > 5) User drives away with a Blue car with 4 square wheels >=20 > Or: > 1) User creates a hints map > 1.1) User sets a wheel ordering - hints.put( WHEEL_ORDERING), {"circl= e","square"} ) > 1.2) User sets a car ordering - hints.put( CAR_ORDERING, {"japanese= ","american"} ) > 2) User creates a CarFactoryFinder( hints ) > 3) User calls CarFactoryFinder.create( Color.Red ) > 3.1) CarFactoryFinder locates japaneseCarFactory using the CAR_ORDERI= NG hint > 3.2) japaneseCarFactory.create( Color.Red, hints ) is called > 3.2.1) japaneseCarFactory creates WheelFactoryFinder( hints ) > 3.2.2) japaneseCarFactory uses WheelFactoryFinder.create( 4 ) > 3.2.3) circleFWheelFactory is found and create() is called 4 times > 3.3) japaneseCarFactory makes a car with the 4 wheels > 4) User drives away with a Red japanese car with 4 circle wheels >=20 > Comments - if I have the above usecases wrong please answer with anothe= r=20 > use case. ??? I'm not sure to understand the intend of those use cases. Those cars=20 have square wheels or circle wheels as specified in user-provided hints,=20 so those two use cases work as expected (in a virtual world). However,=20 there is a proposal of a rewriting of the second use cases (the step=20 order is different): 3.2.1) WheelFactoryFinder wf =3D new WheelFactoryFinder(); 1.1) wf.setOrdering("circle", "square"); 2) CarFactoryFinder cf =3D new CarFactoryFinder(wf); 1.2) cf.setOrdering{"japanese", "american"); 3) cf.createFooFactory( Color.Red ); The difference is that, in yours proposal, FactoryFinder are created by=20 other FactoryFinders, then configured according user-supplied hints. In=20 my proposal, they are created and pre-configured by the users before to=20 be given to the other FactoryFinders that use them. Lets recall that we have many Factory implementations managed by=20 FactoryFinder, but only one implementation of FactoryFinder for CRS, one implementation of FactoryFinder for geometries, etc. (of=20 course, one implementation doesn't prevent many instances of this=20 implementation). We are not going on the path of Finders for=20 FactoryFinder (i.e. FactoryFinderFinder), are we? If we accept to not=20 follow the path of FactoryFinderFinder, then I think it is okay to let=20 the user specify directly which FactoryFinder he wants to use. It also=20 has the side effect to make custom implementations easier. > You are mostly correct on this, when the user has a specific factory in= =20 > mind they will know about it (and be able to supply us with it). The=20 > problem is all the other code in the code base which uses FactoryFinder= =20 > to locate the "appropriate" factory for the job. Sound like a global 'setOrdering' to me. We can provides both: global=20 and local 'setOrdering'. All we have to do for CRS (for example) is to=20 change all static methods into member methods, and provide a default=20 FactoryFinder as a static final field: public static final FactoryFinder DEFAULT =3D new FactoryFinder(); For peoples who want the behavior available previously as static methods: FactoryFinder.getCRSAuthorityFactory(); (for example) would become: FactoryFinder.DEFAULT.getCRSAuthorityFactory(); Any 'setOrdering' performed on the default factory finder would be=20 global for everyone using the default. Any 'setOrdering' on any other=20 instance of FactoryFinder would be local. > Note Factory Finder really is playing the roll of a container (and has=20 > been for some time), it is just the scope of this container has been th= e=20 > entire application. Narrowing this down to a single Query, DataStore o= r=20 > FeatureType is what is proving hard. >=20 > Martin should we go play in a branch? Much like Chris Holmes suggested.= =20 > I don't want to recomend either of these solutions with out a trial=20 > run. One of the off the shelf solutions may still be better for our ne= eds. >=20 > The origional imageio.spi.ServiceRegistry - how does it handle these=20 > kinds of isses? In my understanding, it handle all above-cited issues: 1) ServiceRegistry behave like a container. 2) Because ServiceRegistry is a container, it can manage the ordering of elements it contains. 3) All instances of ServiceRegistry are independent each other. 4) Each instance of ServiceRegistry load Factories only once (or during an explicit 'lookupProviders' call from the users). Sound like more efficient than org.geotools.factory.FactoryFinder to me, since the later search classes and instantiate them every time 'getFactory' is invoked. 5) Factories are automatically notified when they are registered or unregistered in a ServiceRegistry. This is convenient for tuning configuration, for example self-ordering. #4 is especially important in my point of view. The=20 org.geotools.factory.FactoryFinder behavior defeat any attempt to cache=20 object creations (unless we cache them in static fields). The cost is=20 especially high for both EPSG factories (both yours an mine; the first=20 one because it will reload the full properties file every time someone=20 invokes FactoryFinder.getFactory(...), the second one because setting up=20 the database connection is costly). The only thing I'm aware of that FactoryFinder does and ServiceRegistry=20 don't, is to look at factories specified as a system property. This=20 functionality would be trivial to add on top of ServiceRegistry if we=20 actually use it. We can go in a branch if you want. Martin. |