Hi Carlos,
I see you thrashing around a bit with some of these concepts so I'll try and explain with some background on the principles of ROC (Resource Oriented Computing) I find the comparison to DOS and UNIX glob processing unhelpful as a deeper knowledge of the abstraction will show that both approaches can be implemented with appropriate implementations of language-runtimes (shells) and accessors.
Resource Identifiers are treated as opaque by the infrastructure (the kernel). So when scheduling and resolving it is all based upon loose pattern matching. This is very important for the generality of the abstraction.
NetKernel libraries mostly (where appropriate) use the convention of active URI syntax for accessors. When accessors and their clients use the specialisation of the general URI syntax the URIs become less opaque but arguments can be extracted from the identifier. These arguments are nested URIs that are still to be treated as opaque at this level.
Accessors have a choice about how these argument URIs are treated.
1) Arguments are resource references so they can be used to issue sub-requests. I.e. the arguments are passed are references to resources that the accessor should use. Arguments are aliased into the address space seen by an accessor as: this:param:[argument-name] (excuse the legacy of this:param in the identifier). This provides a level of indirection. So for example an accessor could SOURCE the resource referenced by argument named path with:
context.source("this:param:path"); |
Internally to the NKF API this is translated to
context.source("env:path") |
2) URI's are treated as identifiers to be parsed and processed locally. This is a rare case. It is useful for lightweight passing of values. i.e.
active:addNumbers+a@number:1+b@number:2. Typically you would be better off using data: URIs. The problem is that constructing requests like these are hard because NKF treats "1" as a relative URI and tries to absolutize it against the current working URI of the client. The following method allows an accessor to get the argument identifier as a string to be processed:
String INKFRequestReadOnly.getArgument(String aName); |
Let us look at your example: (code not compiled so excuse typos)
A client uses the following code to issue a request to your accessor:
INKFRequest req = context.createSubRequest("active:existsOnPath"); req.addArgument("executable","data:,diff"); req.addArgument("path","env:path"); req.setAspectClass(IAspectBoolean.class); IAspectBoolean exists = (IAspectBoolean)context.issueSubRequestForAspect(req); |
This would issue a request with the following identifier:
active:existsOnPath+executable@data:,diff+path@env:path |
Inside your existsOnPath accessor you can gain access to the arguments in the following ways with the following results:
// get the identifier or string value of an argument String executableIdentifier = context.getThisRequest().getArgument("executable"); // ASSERT executableIdentifier.equals("data:,diff"); |
// source the resource referenced by the argument and get the result as a string import com.ten60.netkernel.urii.aspect.IAspectString; IAspectString sa=context.sourceForAspect("this:param:executable",IAspectString.class); String executable = sa.getString(); //ASSERT executable.equals("diff"); |
In this example the accessor looks up the executable parameter's identifier and then issues a sub-request. This sub-request will resolve to the layer1 data: URI accessor (imports willing)
Now if we tweak our client code to be the following:
INKFRequest req = context.createSubRequest("active:existsOnPath"); req.addArgument("executable","active:randomExecutable+startsWith@data:,d"); req.addArgument("path","env:path"); req.setAspectClass(IAspectBoolean.class); IAspectBoolean exists = (IAspectBoolean)context.issueSubRequestForAspect(req); |
Assume we have created an accessor that generates a random executable name bound to the identifier active:randomExecutable.
When we execute the request our existsOnPath accessor it will still work. It doesn't know about active:randomExecutable and doesn't need to. It is opaque and contains nested arguments. It simply makes the request for it.
I hope this description and example is helpful. I have deliberately skipped over concepts like current working URI (CWU) and Pass-by-value arguments for simplicity.
The ROC abstraction behind NetKernel has been used and refined over many generations of implementation from it's early days in Hewlett Packard Labs. It isn't perfect but we are pretty happy with it. Not happy enough with it that we are complacent though... we have learned a lot over the last few years guiding new users into the way. NetKernel4 is the works with it's focus on a more coherent ROC user abstraction.