private <T> StructSchema<T> getSchema(
      Class<T> source, DefaultMethodModelRuleExtractionContext context) {
    if (!RuleSource.class.isAssignableFrom(source)
        || !source.getSuperclass().equals(RuleSource.class)) {
      context.add("Rule source classes must directly extend " + RuleSource.class.getName());
    }

    ModelSchema<T> schema = schemaStore.getSchema(source);
    if (!(schema instanceof StructSchema)) {
      return null;
    }

    validateClass(source, context);
    return (StructSchema<T>) schema;
  }
  private <P> void addPropertyLink(
      MutableModelNode modelNode,
      ManagedProperty<P> property,
      ModelSchemaStore schemaStore,
      NodeInitializerRegistry nodeInitializerRegistry) {
    ModelType<P> propertyType = property.getType();
    ModelSchema<P> propertySchema = schemaStore.getSchema(propertyType);
    ModelType<T> publicType = bindings.getPublicSchema().getType();

    validateProperty(propertySchema, property, nodeInitializerRegistry);

    ModelPath childPath = modelNode.getPath().child(property.getName());
    if (propertySchema instanceof ManagedImplSchema) {
      if (!property.isWritable()) {
        ModelRegistrations.Builder builder =
            managedRegistrationBuilder(childPath, property, nodeInitializerRegistry, publicType);
        addLink(modelNode, builder, property.isInternal());
      } else {
        if (propertySchema instanceof ScalarCollectionSchema) {
          ModelRegistrations.Builder builder =
              managedRegistrationBuilder(childPath, property, nodeInitializerRegistry, publicType);
          addLink(modelNode, builder, property.isInternal());
        } else {
          modelNode.addReference(property.getName(), propertyType, modelNode.getDescriptor());
        }
      }
    } else {
      ModelRegistrations.Builder registrationBuilder;
      if (shouldHaveANodeInitializer(property, propertySchema)) {
        registrationBuilder =
            managedRegistrationBuilder(childPath, property, nodeInitializerRegistry, publicType);
      } else {
        registrationBuilder = ModelRegistrations.of(childPath);
      }
      registrationBuilder.withProjection(new UnmanagedModelProjection<P>(propertyType));
      addLink(modelNode, registrationBuilder, property.isInternal());
    }
  }