Re: [projects-dev] Review of Java ClassPath API

Svata Dedic <[email protected]> Sun, 25 May 2003 18:12:12 +0200
Newsgroups gmane.comp.java.netbeans.modules.projects.devel
Organization CollabNet Hosting
Message-ID <[email protected]>
Jaroslav Tulach wrote:
> 
> The recommendation is to merge ClassPath and PathContent functionality 
> and keep only ClassPath.
> 

As I wrote elsewhere - there are two (supposed) types of clients: the
ones who are satisfied with flat model of ClassPath - a list of
individible items (roots of classpath) and need only query/search
interface to that model. This is what "ClassPath" was originally
intended for.

The other client type is more concerned by management, so it should get
the structured model and a basic manipulation APIs to alter the model.
PathContent is meant for this type of clients. This type of clients do
not primarily access/locate/search for resources on the ClassPath
(althoguh they may need it in order to determine the configuration steps).
I count configuration UI into this client type.

If the distinction above is not sufficient to keep the types separate,
alternatives can be:
- merge them together
- ClassPath created by from a PathContent using some factory method

> 
> Mixing API and SPI I.
> ---------------------
> 
> In order to support structured paths a new interface PathResource has 
> been introduced that duplicates and enhances functionality already 
> available in ClassPath.Entry. Moreover this class mixes API with SPI 
> which makes it look even more strange.
> 
> The only valid usecases it was possible to find (because the classpath 
> requirements do not contain anything about structured classpaths) are 

Mea culpa, I will add that section. The requirement here is to allow
adding entities that contribute multiple roots. Such entities should be
treated equally to single-rooted items by the API, both are logical
building blocks for the path/

An example could be "source files" or "compiler output" entities, which
contribute one to many roots to the resulting classpath. Another typical
scenario is to insert another project's output, which may contribute one
to many roots and even imply some additional libraries to be isnserted.


> part of the javadoc documentation and are build around usage of methods 
> PathContent.getAllResources(), PathContent.getResources () and 

Probably I should revisit the documentation -- while "getResources"
gives the content of the path itself, getAllResources() produces a flat
depth-first list of all leaf resources on the path - essentially the
input for ClassPath interface.

> PathResource.getEnvironment(). But the class PathResource contains other 
> methods like isLeaf(), getContents(), etc. It is belived that these 
> methods are SPI (at least there is no usecase for them from API point of 

No, isLeaf() and getContents() is part of the structured model, as
isData() and getFileObjects() is part of FS API model.

Possibly the names are not descriptive enough, or poorly documented. If
so, file me a bug please.

> view), they are only used internally to correctly implement 
> PathContent.getAllResources (). As mixing API and SPI can only cause 

getAllResources() is essentially part of bridge between 2nd client and
1st client style described above. It takes structured path as input and
produces flat model as output.

getAllResources() could, in theory, filter or transform resources
contributed by complex libraries inserted into the path -- but that
would indeed mix SPI/API.

> First of all, the API part of the PathResource shall be moved to 
> ClassPath.Entry (methods isValid(), getEnvironment, getFile, maybe the 
> change listener belong there). The structured functionality shall be 

Change listener is definitely a part of API -- if the client is
interested in validity of entries, it should be able to listen on the
changes.

> handled internally and by a separate API, so users of the 
> ClassPath.getResources() and ClassPath.getAllResources () are not scared 
> by it. Possible solution is to have factory method ClassPath.Entry 

This matches the original intention for having ClassPath and PathContent
as separate types. If ClassPath and PathContent are merged into one 
interface, simple clients would be scared by a number of management 
(add/remove/structure) methods they do not need.

Possibly PathContent should NOT extend ClassPath and rather serve as a
factory for ClassPath instances to keep the separation visible (as noted
above).

> The suggested change is to follow the Registry API design and keep 
> ClassPath and ClassPath.Entry final and under control of the module and 
> provide interfaces and factory methods to create new instances. All the 
> SPI functionality of the ClassPath shall be extracted to an interface, 
> say ClassPathImpl. Plus there shall be a factory method ClassPath 
> Factory.createClassPath (ClassPathImpl impl) that could be used by 
> modules trying to provide their own factory. Also ProxyPathContent shall 
> be replaced by an interface ProxyImpl extends ClassPathImpl and factory 
> method to create ClassPath from it. Other SPI classes shall be changed 
> in such a way as well.

Sorry, I do not exactly follow this paragraph. Supposing that
PathContent (as a management interface) will produce ClassPath
instances, ClassPath / ClassPath.Entry could be well final - they will
only delegate to the relevant PathResource methods or build list from
get[All]Resources.

I must say I do not see an advantage of ClassPathImpl interface, except
that it would allow to separate SPI functions:
- getResources() - provides possibly dynamic content from some storage
- add()
- remove()
- setOrder
from client called methods of the same name -- supposing the storage
handling is ultimately the responsibility of the SPI implementor.
Do you think it is worth to introduce such bridge layer ?

Thanks for the review,
-Svata