Separate out some shared behaviour from the `FileCollectionResolveContext` implementations. Apply this shared behaviour only to those file collections that need to resolve arbitrary user provided paths, and simplify the contract for `FileCollectionResolveContext`.
Add `ConfigurableFileCollection.finalizeValue()` to allow the value of the file collection to be finalized. The initial implementation is too eager, in that it calculates all of the files of the collection. Instead, it should calculate and finalize all of the roots of the collection. Later commits will improve this.