/**
 * Synchronize properties with scatterer members
 *
 * This method synchronizes the properties of CompositeBraggScatterer with the
 * properties of the contained BraggScatterer instances. It adds new properties
 * if required and removed properties that are no longer used (for example
 * because the member that introduced the property has been removed).
 */
void CompositeBraggScatterer::redeclareProperties() {
  std::map<std::string, size_t> propertyUseCount = getPropertyCountMap();

  for (auto it = m_scatterers.begin(); it != m_scatterers.end(); ++it) {
    // Check if any of the declared properties is in this scatterer (and set
    // value if that's the case)
    for (auto prop = propertyUseCount.begin(); prop != propertyUseCount.end();
         ++prop) {
      if ((*it)->existsProperty(prop->first)) {
        prop->second += 1;

        propagatePropertyToScatterer(*it, prop->first,
                                     getPropertyValue(prop->first));
      }
    }

    // Use the properties of this scatterer which have been marked as exposed to
    // composite
    std::vector<Property *> properties =
        (*it)->getPropertiesInGroup(getPropagatingGroupName());
    for (auto prop = properties.begin(); prop != properties.end(); ++prop) {
      std::string propertyName = (*prop)->name();
      if (!existsProperty(propertyName)) {
        declareProperty((*prop)->clone());
      }
    }
  }

  // Remove unused properties
  for (auto it = propertyUseCount.begin(); it != propertyUseCount.end(); ++it) {
    if (it->second == 0) {
      removeProperty(it->first);
    }
  }
}
/**
 * Synchronize properties with scatterer members
 *
 * This method synchronizes the properties of CompositeBraggScatterer with the
 * properties of the contained BraggScatterer instances. It adds new properties
 * if required and removed properties that are no longer used (for example
 * because the member that introduced the property has been removed).
 */
void CompositeBraggScatterer::redeclareProperties() {
  std::map<std::string, size_t> propertyUseCount = getPropertyCountMap();

  for (auto &scatterer : m_scatterers) {
    // Check if any of the declared properties is in this scatterer (and set
    // value if that's the case)
    for (auto &prop : propertyUseCount) {
      if (scatterer->existsProperty(prop.first)) {
        prop.second += 1;

        propagatePropertyToScatterer(scatterer, prop.first,
                                     getPropertyValue(prop.first));
      }
    }

    // Use the properties of this scatterer which have been marked as exposed to
    // composite
    std::vector<Property *> properties =
        scatterer->getPropertiesInGroup(getPropagatingGroupName());
    for (auto &property : properties) {
      const std::string &propertyName = property->name();
      if (!existsProperty(propertyName)) {
        declareProperty(std::unique_ptr<Property>(property->clone()));
      }
    }
  }

  // Remove unused properties
  for (auto &property : propertyUseCount) {
    if (property.second == 0) {
      removeProperty(property.first);
    }
  }
}