std::vector<std::list<Parameterization> > ParameterizedCommand::ExpandParameters(
    unsigned int startIndex, const std::vector<IParameter::Pointer>& parameters)
{
  typedef std::vector<std::list<Parameterization> > ReturnType;

  const unsigned int nextIndex = startIndex + 1;
  const bool noMoreParameters = (nextIndex >= parameters.size());

  const IParameter::Pointer parameter(parameters[startIndex]);
  ReturnType parameterizations;

  if (parameter->IsOptional())
  {
    parameterizations.push_back(std::list<Parameterization>());
  }

  IParameter::ParameterValues parameterValues(parameter->GetValues());
  for (IParameter::ParameterValues::iterator parameterValueItr =
      parameterValues.begin(); parameterValueItr != parameterValues.end(); ++parameterValueItr)
  {
    std::list<Parameterization> combination;
    combination.push_back(
        Parameterization(parameter, parameterValueItr->second));
    parameterizations.push_back(combination);
  }

  // Check if another iteration will produce any more names.
  if (noMoreParameters)
  {
    // This is it, so just return the current parameterizations.
    return parameterizations;
  }

  // Make recursive call
  ReturnType suffixes(ExpandParameters(nextIndex, parameters));
  if (suffixes.empty())
  {
    // This is it, so just return the current parameterizations.
    return parameterizations;
  }

  ReturnType returnValue;
  for (ReturnType::iterator suffixItr = suffixes.begin(); suffixItr
      != suffixes.end(); ++suffixItr)
  {
    for (ReturnType::iterator combinationItr = parameterizations.begin(); combinationItr
        != parameterizations.end(); ++combinationItr)
    {
      std::list<Parameterization> newCombination(*combinationItr);
      newCombination.insert(newCombination.end(), suffixItr->begin(),
          suffixItr->end());
      returnValue.push_back(newCombination);
    }
  }

  return returnValue;
}
  std::vector<Parameterization> CommandManager::GetParameterizations(
      const std::string& serializedParams, const std::vector<SmartPointer<IParameter> >& parameters) const
      throw(SerializationException) {

    std::string serializedParameters(serializedParams);

    if (serializedParameters.empty() || parameters.empty()) {
      return std::vector<Parameterization>();
    }

    std::vector<Parameterization> paramList;

    std::string::size_type commaPosition; // split off each param by looking for ','
    do {
      commaPosition = this->UnescapedIndexOf(serializedParameters, ',');

      std::string idEqualsValue;
      if (commaPosition == std::string::npos) {
        // no more parameters after this
        idEqualsValue = serializedParameters;
      } else {
        // take the first parameter...
        idEqualsValue = serializedParameters.substr(0, commaPosition);

        // ... and put the rest back into serializedParameters
        serializedParameters = serializedParameters.substr(commaPosition + 1);
      }

      const std::string::size_type equalsPosition = this->UnescapedIndexOf(idEqualsValue, '=');

      std::string parameterId;
      std::string parameterValue;
      if (equalsPosition == std::string::npos) {
        // missing values are null
        parameterId = this->Unescape(idEqualsValue);
      } else {
        parameterId = this->Unescape(idEqualsValue.substr(0, equalsPosition));
        parameterValue = this->Unescape(idEqualsValue.substr(equalsPosition + 1));
      }

      for (unsigned int i = 0; i < parameters.size(); i++) {
        const IParameter::Pointer parameter(parameters[i]);
        if (parameter->GetId() == parameterId) {
          paramList.push_back(Parameterization(parameter,
              parameterValue));
          break;
        }
      }

    } while (commaPosition != std::string::npos);

    return paramList;
  }
ParameterizedCommand::Pointer ParameterizedCommand::GenerateCommand(const SmartPointer<Command> command,
    const std::map<std::string, Object::Pointer>& parameters)
{
  // no parameters
  if (parameters.empty())
  {
    ParameterizedCommand::Pointer pCmd(new ParameterizedCommand(command, std::vector<Parameterization>()));
    return pCmd;
  }

  try
  {
    std::vector<Parameterization> parms;

    // iterate over given parameters
    for (std::map<std::string, Object::Pointer>::const_iterator i = parameters.begin();
        i != parameters.end(); ++i)
    {
      std::string key(i->first);

      // get the parameter from the command
      IParameter::Pointer parameter(command->GetParameter(key));

      // if the parameter is defined add it to the parameter list
      if (!parameter)
      {
        return ParameterizedCommand::Pointer(0);
      }
      ParameterType::Pointer parameterType(command->GetParameterType(key));
      if (!parameterType)
      {
        std::string val(*(i->second.Cast<ObjectString>()));
        parms.push_back(Parameterization(parameter, val));
      }
      else
      {
        IParameterValueConverter::Pointer valueConverter(parameterType
            ->GetValueConverter());
        if (valueConverter)
        {
          std::string val(valueConverter->ConvertToString(i->second));
          parms.push_back(Parameterization(parameter, val));
        }
        else
        {
          std::string val(*(i->second.Cast<ObjectString>()));
          parms.push_back(Parameterization(parameter, val));
        }
      }
    }

    // convert the parameters to an Parameterization array and create
    // the command
    ParameterizedCommand::Pointer pCmd(new ParameterizedCommand(command, parms));
    return pCmd;
  }
  catch (const NotDefinedException* /*e*/)
  {
  }
  catch (const ParameterValueConversionException* /*e*/)
  {
  }
  return ParameterizedCommand::Pointer(0);
}
SmartPointer<ParameterizedCommand> RegistryPersistence::ReadParameters(
    const SmartPointer<IConfigurationElement>& configurationElement,
    QList<SmartPointer<IStatus> >& warningsToLog,
    const SmartPointer<Command>& command)
{
  const QList<IConfigurationElement::Pointer> parameterElements = configurationElement
      ->GetChildren(TAG_PARAMETER);
  if (parameterElements.isEmpty())
  {
    ParameterizedCommand::Pointer result(new ParameterizedCommand(command, QList<Parameterization>()));
    return result;
  }

  QList<Parameterization> parameters;
  foreach (const IConfigurationElement::Pointer& parameterElement, parameterElements)
  {
    // Read out the id.
    const QString id = parameterElement->GetAttribute(ATT_ID);
    if (id.isEmpty())
    {
      // The id should never be null. This is invalid.
      AddWarning(warningsToLog, "Parameters need an id", configurationElement);
      continue;
    }

    // Find the parameter on the command.
    IParameter::Pointer parameter;
    try
    {
      const QList<IParameter::Pointer> commandParameters = command->GetParameters();
      foreach (const IParameter::Pointer& currentParameter, commandParameters)
      {
        if (currentParameter->GetId() == id)
        {
          parameter = currentParameter;
          break;
        }
      }
    }
    catch (const NotDefinedException& /*e*/)
    {
      // This should not happen.
    }
    if (parameter.IsNull())
    {
      // The name should never be null. This is invalid.
      AddWarning(warningsToLog, "Could not find a matching parameter",
                 configurationElement, id);
      continue;
    }

    // Read out the value.
    const QString value = parameterElement->GetAttribute(ATT_VALUE);
    if (value.isEmpty())
    {
      // The name should never be null. This is invalid.
      AddWarning(warningsToLog, "Parameters need a value",
                 configurationElement, id);
      continue;
    }

    parameters.push_back(Parameterization(parameter, value));
  }

  if (parameters.isEmpty())
  {
    ParameterizedCommand::Pointer result(new ParameterizedCommand(command, QList<Parameterization>()));
    return result;
  }

  ParameterizedCommand::Pointer result(new ParameterizedCommand(command, parameters));
  return result;
}
QList<QList<Parameterization> > ParameterizedCommand::ExpandParameters(
    unsigned int startIndex, const QList<IParameter::Pointer>& parameters)
{
  typedef QList<QList<Parameterization> > ReturnType;

  const int nextIndex = startIndex + 1;
  const bool noMoreParameters = (nextIndex >= parameters.size());

  const IParameter::Pointer parameter(parameters[startIndex]);
  ReturnType parameterizations;

  if (parameter->IsOptional())
  {
    parameterizations.push_back(QList<Parameterization>());
  }

  IParameterValues* values = NULL;
  try
  {
    values = parameter->GetValues();
  }
  catch (const ParameterValuesException& /*e*/)
  {
    if (noMoreParameters)
    {
      return parameterizations;
    }

    // Make recursive call
    return ExpandParameters(nextIndex, parameters);
  }

  const QHash<QString,QString> parameterValues = values->GetParameterValues();
  for (IParameter::ParameterValues::const_iterator parameterValueItr =
      parameterValues.begin(); parameterValueItr != parameterValues.end(); ++parameterValueItr)
  {
    QList<Parameterization> combination;
    combination.push_back(
        Parameterization(parameter, parameterValueItr.value()));
    parameterizations.push_back(combination);
  }

  // Check if another iteration will produce any more names.
  if (noMoreParameters)
  {
    // This is it, so just return the current parameterizations.
    return parameterizations;
  }

  // Make recursive call
  ReturnType suffixes(ExpandParameters(nextIndex, parameters));
  if (suffixes.empty())
  {
    // This is it, so just return the current parameterizations.
    return parameterizations;
  }

  ReturnType returnValue;
  for (ReturnType::iterator suffixItr = suffixes.begin(); suffixItr
      != suffixes.end(); ++suffixItr)
  {
    for (ReturnType::iterator combinationItr = parameterizations.begin(); combinationItr
        != parameterizations.end(); ++combinationItr)
    {
      QList<Parameterization> newCombination(*combinationItr);
      newCombination.append(*suffixItr);
      returnValue.push_back(newCombination);
    }
  }

  return returnValue;
}