private <R, S extends BinarySpec> ExtractedModelRule createRegistration(
      MethodRuleDefinition<R, ?> ruleDefinition) {
    try {
      RuleMethodDataCollector dataCollector = new RuleMethodDataCollector();
      verifyMethodSignature(dataCollector, ruleDefinition);

      final Class<S> binaryType = dataCollector.getParameterType(BinarySpec.class);
      final BinaryTaskRule<R, S> binaryTaskRule =
          new BinaryTaskRule<R, S>(binaryType, ruleDefinition);
      return new ExtractedModelAction(
          ModelActionRole.Defaults,
          ImmutableList.of(ComponentModelBasePlugin.class),
          DirectNodeNoInputsModelAction.of(
              ModelReference.of("binaries"),
              new SimpleModelRuleDescriptor("binaries*.create()"),
              new Action<MutableModelNode>() {
                @Override
                public void execute(MutableModelNode modelNode) {
                  modelNode.applyToAllLinks(ModelActionRole.Finalize, binaryTaskRule);
                }
              }));
    } catch (InvalidModelException e) {
      throw invalidModelRule(ruleDefinition, e);
    }
  }
  private <T> void registerAction(
      final ModelPath modelPath,
      final Class<T> viewType,
      final ModelRuleDescriptor descriptor,
      final ModelActionRole role,
      final Closure<?> closure) {
    final ModelReference<T> reference = ModelReference.of(modelPath, viewType);
    modelRegistry.configure(
        ModelActionRole.DefineRules,
        DirectNodeNoInputsModelAction.of(
            reference,
            descriptor,
            new Action<MutableModelNode>() {
              @Override
              public void execute(MutableModelNode mutableModelNode) {
                InputReferences inputs = inputPathsExtractor.transform(closure);
                List<String> absolutePaths = inputs.getAbsolutePaths();
                List<Integer> absolutePathLineNumbers = inputs.getAbsolutePathLineNumbers();
                final List<PotentialInput> potentialInputs =
                    Lists.newArrayListWithCapacity(absolutePaths.size());
                List<ModelReference<?>> actualInputs =
                    Lists.newArrayListWithCapacity(potentialInputs.size());

                for (int i = 0; i < absolutePaths.size(); i++) {
                  String description = String.format("@ line %d", absolutePathLineNumbers.get(i));
                  String path = absolutePaths.get(i);
                  potentialInputs.add(PotentialInput.absoluteInput(path, actualInputs.size()));
                  actualInputs.add(ModelReference.untyped(ModelPath.path(path), description));
                }
                mutableModelNode.applyToSelf(
                    role,
                    InputUsingModelAction.of(
                        reference,
                        descriptor,
                        actualInputs,
                        new BiAction<T, List<ModelView<?>>>() {
                          @Override
                          public void execute(final T t, List<ModelView<?>> modelViews) {
                            ((TransformedClosure) closure)
                                .applyRuleInputs(new PotentialInputs(modelViews, potentialInputs));
                            ClosureBackedAction.execute(
                                t,
                                closure.rehydrate(
                                    null, closure.getThisObject(), closure.getThisObject()));
                          }
                        }));
              }
            }));
  }