Home » Modeling » B3 » A better way to handle repository and resolution
|A better way to handle repository and resolution [message #532316]
||Fri, 07 May 2010 21:35
| Henrik Lindberg
Registered: July 2009
I have been working on the handling of repository and resolution for a
while - we decided on syntax a while back, and I got a majority of that
I have since then been thinking about how to bind a b3 script to a
particular implementation. An I now have an idea for how this should be
designed to provide the wanted separation and flexibility.
- We do not want the grammar (and editor) to be tied to a particular
- It should be possible to add new repository types and new resolver types.
- The editor should be capable of handling code completion/proposals etc.
I considered multiple solutions - and here is a brain dump:
When editing: Solution 1
- For each repository type (i.e. "p2", "svn", "git") an extension is
added for the editing environment. This extension point provides the
name of the repository ("svn"), and two classes - one class for the
repository, and one for resolvers using this repository. Lets call these
- When editing, and a validator can not be found for the repository type
used in the b3 text, the editor issues a Warning (or possibly an Error,
or configurable in preferences).
- A validator is responsible for providing the b3 grammar validator with
- does the repository support branches
- the BranchPoint types it supports (tag, revision, timestamps, or
- validation of a series of 'key = expr' in the form of "valid
keys", "type of expr"
- input to the "code completion"/"proposal" (i.e. suggest keys,
- If a validator is not found for the repository type (or for a
resolution referencing a repository without a validator) any key and any
expr type is allowed but flagged as a warning (optionally as an error).
- We can then decode all of the keys for a repository as such
validations and the grammar can just use ID instead of hardwired
keywords (with use of syntax coloring etc. it will look exactly the same
to the user). This has the benefit of not polluting the keyword space
with popular words like "location", "uri", "user", "password" etc. or
use more contrived keywords like "repository-user".
- A "maven" repository that requires mapping of requested unit to a
groupId, artifactId, could simply have an expression that looks like this:
mavenId = [groupId: expr, artifactId: expr]
where validation checks that the map has the correct keys, and correct
type (string in this case). The expressions could be arbitrarily
complex. (These expressions are evaluated in a context where 'request'
is bound so name and namespace, version (range) can be picked up from
Pros and cons
+ straight forward to implement
+ relatively simply to extend
- nested structures are difficult to handle (the mavenId is a simple
example of a nested structure)
Alternative Solution When Editing - Ecore extensions
- the extension point for repository name refers to an Ecore model, and
a feature in this model
- The feature must be a class inheriting RepositoryHandler from the
- Validation uses model reflection to figure out available features and
their types - literals are mapped to literal expressions, all other
expressions require the model to accept BExpression (to be evaluated).
- However, introducing grammar to handle an arbitrary model quickly gets
quite complex, the current grammar would handle this using the new
operator configuring the created instance, but this requires several
things not currently supported to be convenient (currently the user
would need to import the generated classes and use the new operator).
Even if it was made possible to instantiate model instances, it becomes
difficult to get around using a new operator and reference the actual
wanted type (say a relationship to an abstract base class where a
particular derived class should be instantiated).
Pros and Cons
+ Powerful extension mechanism
- Longer time to implement (difficult to be complete)
- Syntax difficulties (takes time to resolve and design)
Alternative Solution - archtypes
An alternative is to let b3 grammar / language actually know about the
repository types (the set of repository types have evolved very slowly
in Buckminster for instance). The language does not have to know about
each type, cvs, svn, p4 can be handled the same way (with only minor
difference between what they support in terms of tags, revisions and
timestamps), git is very similar. The p2 and maven repositories are well
known types, p2 repo description requires only the most basic
information. Maven has the special two part identifier to consider.
All these could easily be covered with simple declarative syntax.
The Buckminster URL repository is the most complex to handle
(essentially a scraper reading HTML/XML and picking out interesting
parts that declarative parts act on to determine some facts about the
component(s) found). In b3, it would be more natural to just provide
this as a configurable repository with lambda expressions that allow the
user to do just about anything - but translating such general
expressions to the URL reader in Buckminster becomes an issue.
It is probably easier to let Buckminster just call b3 :)
Instead, b3 could have the notion of a configurable-scanner repository
basically consisting of a type and a pointer to a configuration URI.
This would enable referencing a Buckminster URL mapper by pointing to a
RMAP file and providing the name of a reader.
The solution is that b3 knows about archetypes of repositories:
- SCMs (cvs, svn, git, p4)
- Maven (maven1, maven2) - basically dual id support, which could just
as well be maven specific
- SimpleRepo (p2) - just the repo data (uri, user, password), no branches.
At authoring time these are easy to validate and to provide quickfixes etc.
This solution would be easy to combine with solution 1 (simple
validators via extension points).
Pros and Cons
+ Easy to implement
+ Opaque stuff can be handled with alternative implementations if
someone wants to - semantics are tied to an interface defined by some
implementation of a technology
- semantics are clear from b3 albeit pushing of the most complex into an
opaque corner grammar wise
- An engine is used to evaluate a b3 script
- We use google guice to bind to a particular implementation (using
guice means instances are created using an injector configured to use a
set of Modules, where a Module binds interfaces to implementations, and
injects them as needed. Guice also handles "roles" which is important in
our case (see below).
- We simply use guice to map a repository type name (e.g. "svn") to a
IRepositoryHandler of role "svn"
- The binding can be dynamic (i.e. discovered at runtime from extension
points) i.e. a buckminster engine module will bind the reader types it
finds as extensions in the runtime.
I think the archetype solution is the best compromise between ease of
use, ease of implementation, and power/flexibility. I plan to explore
the impl of this solution over the next couple of days. Comments are
welcome (the sooner the better :)
Current Time: Mon Mar 10 12:49:14 EDT 2014
Powered by FUDForum
. Page generated in 0.05008 seconds