/**
  * Add {@link FlowPropertyDefinition}s from the flowPropertyDefinitionProviders as a flow for each
  * property.
  *
  * <p>Only the properties that have {@link FlowPropertyDefinition#getPropertyUsage()}.{@link
  * PropertyUsage#isOutputedProperty()} != false get their own flow. This makes it safe to list
  * properties that are expected on input without having a flow created for those input only
  * properties.
  *
  * @param flowPropertyDefinitionProviders
  */
 public void add(FlowPropertyDefinitionProvider... flowPropertyDefinitionProviders) {
   for (FlowPropertyDefinitionProvider flowPropertyDefinitionProvider :
       flowPropertyDefinitionProviders) {
     List<String> outputFlowPropertyDefinitionNames =
         flowPropertyDefinitionProvider.getOutputFlowPropertyDefinitionNames();
     FlowConfigurationException.valid(
         isNotEmpty(outputFlowPropertyDefinitionNames),
         flowPropertyDefinitionProvider.getClass(),
         " has no output properties defined.");
     for (String flowPropertyName : outputFlowPropertyDefinitionNames) {
       // TODO : should we apply expectations: readonly?
       this.add(flowPropertyName, flowPropertyDefinitionProvider, null);
     }
   }
 }
  /**
   * {@link FlowPropertyDefinitionProvider} can supply multiple properties. {@link
   * #add(FlowPropertyDefinitionProvider...)} creates flows from {@link
   * FlowPropertyDefinitionProvider#getOutputFlowPropertyDefinitionNames()} property list (if
   * supplied) or the first property defined.
   *
   * <p>Using this add() method allows the other properties to also be accessed in their own flow.
   *
   * @param flowPropertyName
   * @param flowPropertyDefinitionProvider
   * @param additionalConfigurationParameters
   */
  public void add(
      String flowPropertyName,
      FlowPropertyDefinitionProvider flowPropertyDefinitionProvider,
      List<FlowPropertyExpectation> additionalConfigurationParameters) {
    String capitalizedFlowPropertyName = StringUtils.capitalize(flowPropertyName);
    FlowImpl flow = new FlowImpl(capitalizedFlowPropertyName);
    flow.addPropertyDefinitions(
        new FlowPropertyDefinitionBuilder(FSSINGLE_PROPERTY_NAME)
            .internalOnly()
            .initDefaultObject(flowPropertyName));

    FlowActivityImpl flowActivity = new FlowActivityImpl("FA");
    // TODO: use to reduce impact of the expectations?
    // otherwise don't we risk exposing internal parameters.
    // FlowPropertyDefinitionBuilder.merge(new FlowPropertyExpectationImpl(flowPropertyName),
    // additionalConfigurationParameters);

    flowPropertyDefinitionProvider.defineFlowPropertyDefinitions(
        flowActivity, additionalConfigurationParameters);
    flow.addActivity(flowActivity);
    put(this.flows, flow.getFlowPropertyProviderFullName(), flow);
  }