- Change implementation of
components
node to eagerly create asource
child node for each element node, with the object returned bycomponentSpec.sources
components.«name».source
is projected using the unmanaged projection (i.e. it is opaque)- Use
.all()
hook of component's source set container to create the child nodes of thesource
node as unmanaged node, based on type of the source set given to the origin create() method - Change all removal type operations of
«component».source
to throwUnsupportedOperationException
Can referencecomponents.«component».source
in a rule (by path, can't bind by type for non top level)source
node is displayed for each component in the component containerCan referencecomponents.«component».source.«source set»
in a rule (by path, can't bind by type for non top level)Can referencecomponents.«component».source.«source set»
in a rule as a matching specialisation ofLanguageSourceSet
source.«sourceSet»
node is displayed for each source set of each component in the component containerExisting usages ofProjectSourceSet
continue to work, and corresponding rootsources
node (changing anything here is out of scope)Removal of source sets throwsUnsupportedOperationException
- Removing source sets from components no longer supported
The goal for this feature is to expose something like the following structure to rules:
project (aka 'model')
+-- components
| +-- <component-name>
| +-- sources
| | +-- <source-set-name>
| +-- binaries
| +-- <binary-name>
+-- testSuites
+-- <test-suite-name>
+-- <same-structure-as-component-above>
For this feature, it is a non-goal to expose any public mechanism for implementing this structure, but this isn't necessarily ruled out either. The implementation may be fully internal and not extensible (other than adding elements to the various collections above).
At the completion of this feature, it should be possible to:
- Run the
model
report to see something like the above structure. - Use the rule DSL to configure any of the objects above selected using hard-coded path.
One possible approach is to add each relationship to the graph incrementally, one at a time, fixing the inevitable breakages before moving to the next.
An implementation could use the internal MutableModelNode
type to expose each relationship as an edge between two nodes with unmanaged values.
Rules hardcoded in the component base plugins can attach these node and edges as the appropriate model elements become known.
The collections in the graph above are currently represented using DomainObjectSet
. One possible implementation is to listen for changes to these collections
and attach node and edges as elements are added, bridging the legacy collections into the model graph.
Possibly a better implementation would be to change CollectionBuilder
into a 'managed map' and use a managed implementation
(not the existing bridged implementation) for these collections instead. This approach would mean some interleaving of this feature and the next.
- Remove the ability to view/mutate the component container as a domain object set
- Remove the “bridging” of the component container outside of model space
- Remove
components
project extension - Remove model projection that allows access as a domain object set
- Change
ComponentSpecContainer
toextends CollectionBuilder<ComponentSpec>
- Add the necessary, possibly adhoc, projection that presents a view that is a ComponentSpecContainer impl
Some, internal only, mechanism will also need to be added to keep the functionality of ExtensiblePolymorphicDomainObjectContainer
.
That is, the ability to register a kind of factory for new component types.
This story doesn't dictate any kind of implementation for the actual model node other than the ability to project as a ComponentSpecContainer
(and CollectionBuilder<T extends ComponentSpec>
sub collections)
- Can view the components container as a
ComponentSpecContainer
- Can view the components container as a sub set
CollectionBuilder<T>
where T extendsComponentSpec
(e.g.PlayCoffeeScriptPlugin.createCoffeeScriptSourceSets
) - DSL type methods (e.g. Action → Closure) methods can be used on a
ComponentSpecContainer
- Can continue to register custom component types (i.e.
@ComponentType
rules still work)
Most of this coverage already exists, need to fill in the gaps:
Build script can:Create a component using a registered component type.Configure components:With given nameWith given typeAll components
Apply beforeEach/afterEach rules to components.
Plugin can do the above.Reasonable error message when:Attempting to create a component using a type for which there is no implementation.Attempting to create a component using default type.
- Removal of
project.componentSpecs
- Removal of ability to bind to the component container as
ExtensiblePolymorphicDomainObjectContainer<ComponentSpec>
(if this ever actually worked) - Removal of
ExtensiblePolymorphicDomainObjectContainer<ComponentSpec>
methods fromComponentSpecContainer
, addition of collection builder methods - All configuration done using subject of type
ComponentSpecContainer
is deferred. Used to be eager.
- Change implementation of
components
node to eagerly create abinaries
child node for each element node, with the object returned bycomponentSpec.binaries
components.«name».binaries
is projected using the unmanaged projection (i.e. it is opaque)- Use
.all()
hook of component's binaries container to create the child nodes of thebinaries
node as unmanaged node, based on the runtime type of the binary - Change all removal type operations of
«component».binaries
to throwUnsupportedOperationException
Can referencecomponents.«component».binaries
in a rule (by path, can't bind by type for non top level)binaries
node is displayed for each component in the component reportCan referencecomponents.«component».binaries.«binary»
in a rule (by path, can't bind by type for non top level)Can referencecomponents.«component».binaries.«binary»
in a rule as a matching specialisation ofBinarySpec
binaries.«binary»
node is displayed for each source set of each component in the component containerExisting usages ofBinarySpec
continue to work, and corresponding rootbinaries
node (changing anything here is out of scope)Removal of binaries throwsUnsupportedOperationException
- Removing binaries from components no longer supported
The test suite container has the same level of management/visibility as the general component container
Effectively the same treatment that the component spec container received.
Implementation should refactor ComponentModelBasePlugin
and NativeBinariesTestPlugin
so that this behaviour is reused for the test suite container and not
duplicated.
Story: Use ModelMap
instead of various domain object collection types in public API of component model
- Change the methods currently using domain object collections (i.e.
ComponentSpec.getSource()
,ComponentSpec.sources()
,ComponentSpec.getBinaries()
,ComponentSpec.binaries()
to useModelMap
. - Create new implementations of
ModelMap
that are backed by appropriate domain object collection and use them in implementation of the above methods. - Backing these implementations with domain object collection types means that they will be eager.
Existing test coverage still works.
ComponentSpec.getSource()
now returns aModelMap<LanguageSourceSet>
instead ofDomainObjectSet<LanguageSourceSet>
.ComponentSpec.sources()
now takes aAction<? super ModelMap<LanguageSourceSet>>
instead ofAction<? super PolymorphicDomainObjectContainer<LanguageSourceSet>>
.ComponentSpec.getBinaries()
now returns aModelMap<BinarySpec>
instead ofNamedDomainObjectCollection<BinarySpec>
.ComponentSpec.binaries()
now takes aAction<? super ModelMap<BinarySpec>>
instead ofAction<? super NamedDomainObjectContainer<BinarySpec>>
.
This feature changes the software model to introduce 'managed map' types instead of DomainObjectSet
.
- The property
ComponentSpec.sources
, a collection ofLanguageSourceSet
, should allow anyLanguageSourceSet
type registered using a@LanguageType
rule to be added. - The property
ComponentSpec.binaries
, a collection ofBinarySpec
, should allow anyBinarySpec
type registered using a@BinaryType
rule to be added.
At the completion of this feature, it should be possible to write 'before-each', 'after-each', 'all with type' etc rules for the source sets and binaries of a component. These rules will be executed as required.
This feature does not require that sources, binaries etc. of the component model are actually deferred under conventional use. Some of the infrastructure rules in the component model plugins are currently coarse in that they effectively depend on all the components, forcing realisation. This feature does not require changing the implementation of these rules to be more fine grained. It does require that the elements are potentially deferrable.
Again, a possible approach is to change each collection, one at a time, and fix the breakages before moving on to the next collection. Breakages are expected as configuration for the elements of these collections will be deferred, whereas it is currently performed eagerly.
This feature requires a managed map implementation whose values are unmanaged, which means some kind of internal factory will be required for this implementation
(such as NamedEntityInstantiator
).
Currently the DSL supports nested, eager, configuration of these elements:
model {
component {
someThing {
sources {
cpp { ... }
}
binaries {
all { ... }
}
}
}
}
Some replacement for this nesting should be offered, and the configuration deferred.
This story changes the sources
property of ComponentSpec
to be of type (the new with this story) ModelMap<LanguageSourceSet>
.
The model map will be entirely model graph backed, and not “bridge” a collection.
This allows actually creating the source sets to be deferred.
ModelMap
is replacement for the existing CollectionBuilder
, and DomainObjectContainer
from non-rules world.
It should actually extend CollectionBuilder
, which will later be removed and inlined into ModelMap
.
ModelMap
does not need to actually implement Map
at this time.
Existing usages of CollectionBuilder
do not necessarily need to be changed to ModelMap
.
However, if it makes things easier (e.g. reuse of projections) then we should do this.
If so, CollectionBuilder
must go through a deprecate cycle and still be usable (e.g. as a type binding target) for one release.
After the change, the DSL for working with component source sets should be largely unchanged.
Particularly, the familiar nested closure syntax.
It is not a requirement that ModelMap
is structurally compatible with NamedDomainObjectSet and friends, but supports the same patterns in so far as CollectionBuilder
already does.
- Component spec source sets are not realised when only another property of the component is required (e.g. rule depends on
component.binaries
) - Only required component source set is realised (e.g. rule depends on
component.sources.main
does not realisecomponent.sources.other
) - Specification of source set for component in DSL does not eagerly create the source set (i.e. existing container DSL syntax can still be used, but source set is no longer eagerly created)
- Can use
withType()
,named()
etc. methods to attach rules to specific source sets
component.sources
no longer aDomainObjectSet
component.source(Action)
no longer operates on aPolymorphicDomainObjectContainer
- Potential deprecation (for removal in next release) of
CollectionBuilder
(replaced byModelMap
)
- Implications for FunctionalSourceSet and project level source set container?