Currently the spec provides a somewhat odd mix of functionality here...
1. Module name. We have declaration syntax (superpackage name) and runtime support for using a module name as a constraint (ImportDependency class and Query.name()). 2. Versions. We have declaration syntax (VersionConstraint annotation) and runtime support for using a collection of version/version-ranges as a constraint (VersionConstraint/ImportDependency classes, and Query.version()). 3. Attributes. We have declaration syntax for *assigning* attributes to a definition (ModuleAttributes annotation), but no declaration syntax for using them as constraints (a custom ImportPolicy is required). We have runtime support for using them as constraints (Query.attribute()). 4. Extensible constraints. We have no declaration syntax, but we *do* have runtime support for expressing any type of constraint and combining them with boolean operators (Query). I'd like to emphasize that Query should be seen *as the runtime representation of a constraint*, and that: Any import declaration must be expressible as a Query. This includes the module name (and potentially a package name, TBD). This last is an important point: other than optimizing searches, a module name is not special! It's just another Query element (ditto for a package name Query), evaluated along with any others in a compound Query (i.e. Query elements combined with boolean operators). A definition can even be looked up *without* a module name, using nothing but attribute matching. When I initially designed Query (and Repository.find()), I wanted something very flexible and extensible, with the expectation that it could be used to represent the entire constraint model. But I don't think we're using it as effectively as we can... Ok, so? Well, first, I think we ought to generalize the runtime dependency type to fully leverage Query. So change ImportDependency to: public class ImportDependency extends Query { private Query constraint; private boolean optional; private boolean reExport; public ImportDependency (Query constraint, boolean optional, boolean reExport) { this.constraint = constraint; this.optional = optional; this.reExport = reExport; } public boolean match(ModuleDefinition target) { return constraint.match(target); } public boolean isOptional() { return optional; } public boolean isReExported() { return reExport; } public String toString() { ... } } This way, we rely on the flexibility of Query to express *all* constraints, and have a single concrete type to represent dependencies. By having Dependency extend Query, instances can be directly passed to Repository.find(); no conversion required. We could obviously just make a getter for the Query if we want, but why not make this convenient to use? And, more importantly, ModuleDefinition.getImportDependency() implementations are free to return any kind of constraints they want, simply by varying the Query. Module name, if present, is just a Query element. Again, I think the only place this (and/or package name) is explicitly needed is to enable search *optimization*: if we want to avoid linear searches in Repository.findModuleDefinition(Query) implementations, there needs to be a way to narrow the search efficiently. But it's just an optimization, and a topic for a different thread. Second, I think we should eliminate VersionConstraint as a separate class. It's functionality is easy to replace with Query elements that match Version or VersionRange, strung together with appropriate boolean operators. Third, we should add a getExportedPackages() method to ModuleDefinition. This way a Query can easily be created to search by package name. Whether or not we choose to surface import-by-package declaratively, it should at least be possible for a ModuleSystem to use such a Query. Fourth, we should add support for simple attribute constraint declarations. Enabling simple equality constraints ought to be easy enough: an AttributeConstraint annotation that takes key/value lists (key1==value1;key2==value2;...). We already have support for expressing these as Query instances. This simple type of attribute constraint is supported by OSGi. I don't have a good sense of how common its usage is (Glyn/Richard?), but some will likely view the absence of this support in 277 as an interoperability issue. More complex attribute comparisons could still be left up to custom import policies. Or... <dreaming-out-loud> We could instead create a generic *query* declaration syntax, with support for expressing module-name, package-name, version, version-range, attribute matching, as well as boolean operators and precedence. This would eliminate the need for VersionConstraint/AttributeConstraint annotations. The current VersionConstraint syntax using ";" separators would no longer be required, as the boolean operators could be used instead. And the expressiveness might reduce or eliminate the need for many custom import policies. </dreaming-out-loud> Finally, Query ought to have a toString() implementation so that we can log them, examine in a debugger, put them in error messages, etc. Regardless of the approach, it would certainly be nice to provide some symmetry between our declarative syntax and our runtime capabilities. Thoughts? // Bryan