private ModelReference<?> mapSubject(ModelReference<?> subject, ModelPath targetPath) {
   if (subject.getPath() == null) {
     return subject.inScope(targetPath);
   } else {
     return subject.withPath(targetPath.descendant(subject.getPath()));
   }
 }
 private void mapInputs(List<ModelReference<?>> inputs, ModelPath targetPath) {
   for (int i = 0; i < inputs.size(); i++) {
     ModelReference<?> input = inputs.get(i);
     if (input.getPath() != null) {
       inputs.set(i, input.withPath(targetPath.descendant(input.getPath())));
     } else {
       inputs.set(i, input.inScope(ModelPath.ROOT));
     }
   }
 }
 @Override
 protected List<ModelReference<?>> withImplicitInputs(List<? extends ModelReference<?>> inputs) {
   List<ModelReference<?>> allInputs =
       new ArrayList<ModelReference<?>>(inputs.size() + implicitInputs.size());
   allInputs.addAll(inputs);
   for (ModelProperty<?> property : implicitInputs) {
     ManagedInstance value = (ManagedInstance) values.get(property.getName());
     allInputs.add(ModelReference.of(value.getBackingNode().getPath()));
   }
   return allInputs;
 }
  private void validateRuleMethod(
      MethodRuleDefinition<?, ?> ruleDefinition,
      Method ruleMethod,
      ValidationProblemCollector problems) {
    if (Modifier.isPrivate(ruleMethod.getModifiers())) {
      problems.add(ruleMethod, "A rule method cannot be private");
    }
    if (Modifier.isAbstract(ruleMethod.getModifiers())) {
      problems.add(ruleMethod, "A rule method cannot be abstract");
    }

    if (ruleMethod.getTypeParameters().length > 0) {
      problems.add(ruleMethod, "Cannot have type variables (i.e. cannot be a generic method)");
    }

    // TODO validations on method: synthetic, bridge methods, varargs, abstract, native
    ModelType<?> returnType = ModelType.returnType(ruleMethod);
    if (returnType.isRawClassOfParameterizedType()) {
      problems.add(
          ruleMethod,
          "Raw type "
              + returnType
              + " used for return type (all type parameters must be specified of parameterized type)");
    }

    for (int i = 0; i < ruleDefinition.getReferences().size(); i++) {
      ModelReference<?> reference = ruleDefinition.getReferences().get(i);
      if (reference.getType().isRawClassOfParameterizedType()) {
        problems.add(
            ruleMethod,
            "Raw type "
                + reference.getType()
                + " used for parameter "
                + (i + 1)
                + " (all type parameters must be specified of parameterized type)");
      }
      if (reference.getPath() != null) {
        try {
          ModelPath.validatePath(reference.getPath().toString());
        } catch (Exception e) {
          problems.add(
              ruleDefinition,
              "The declared model element path '"
                  + reference.getPath()
                  + "' used for parameter "
                  + (i + 1)
                  + " is not a valid path",
              e);
        }
      }
    }
  }