text: /***************************************************************************
   *   Copyright (C) by GFZ Potsdam                                          *
   *                                                                         *
   *   You can redistribute and/or modify this program under the             *
   *   terms of the SeisComP Public License.                                 *
   *                                                                         *
   *   This program is distributed in the hope that it will be useful,       *
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
   *   SeisComP Public License for more details.                             *
   ***************************************************************************/
  
  
  #define SEISCOMP_COMPONENT DataModel
  #include <seiscomp3/datamodel/parameterset.h>
  #include <seiscomp3/datamodel/config.h>
  #include <seiscomp3/datamodel/parameter.h>
  #include <algorithm>
  #include <seiscomp3/datamodel/metadata.h>
  #include <seiscomp3/logging/log.h>
  
  
  namespace Seiscomp {
  namespace DataModel {
  
  
  IMPLEMENT_SC_CLASS_DERIVED(ParameterSet, PublicObject, "ParameterSet");
  
  
  ParameterSet::MetaObject::MetaObject(const Core::RTTI* rtti) : Seiscomp::Core::MetaObject(rtti) {
  	addProperty(Core::simpleProperty("baseID", "string", false, false, false, true, false, false, NULL, &ParameterSet::setBaseID, &ParameterSet::baseID));
  	addProperty(Core::simpleProperty("moduleID", "string", false, false, false, true, false, false, NULL, &ParameterSet::setModuleID, &ParameterSet::moduleID));
  	addProperty(Core::simpleProperty("created", "datetime", false, false, false, false, true, false, NULL, &ParameterSet::setCreated, &ParameterSet::created));
  	addProperty(arrayObjectProperty("parameter", "Parameter", &ParameterSet::parameterCount, &ParameterSet::parameter, static_cast<bool (ParameterSet::*)(Parameter*)>(&ParameterSet::add), &ParameterSet::removeParameter, static_cast<bool (ParameterSet::*)(Parameter*)>(&ParameterSet::remove)));
  	addProperty(arrayClassProperty<Comment>("comment", "Comment", &ParameterSet::commentCount, &ParameterSet::comment, static_cast<bool (ParameterSet::*)(Comment*)>(&ParameterSet::add), &ParameterSet::removeComment, static_cast<bool (ParameterSet::*)(Comment*)>(&ParameterSet::remove)));
  }
  
  
  IMPLEMENT_METAOBJECT(ParameterSet)
  
  
  ParameterSet::ParameterSet() {
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  ParameterSet::ParameterSet(const ParameterSet& other)
  : PublicObject() {
  	*this = other;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  ParameterSet::ParameterSet(const std::string& publicID)
  : PublicObject(publicID) {
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  ParameterSet::~ParameterSet() {
  	std::for_each(_parameters.begin(), _parameters.end(),
  	              std::compose1(std::bind2nd(std::mem_fun(&Parameter::setParent),
  	                                         (PublicObject*)NULL),
  	                            std::mem_fun_ref(&ParameterPtr::get)));
  	std::for_each(_comments.begin(), _comments.end(),
  	              std::compose1(std::bind2nd(std::mem_fun(&Comment::setParent),
  	                                         (PublicObject*)NULL),
  	                            std::mem_fun_ref(&CommentPtr::get)));
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  ParameterSet* ParameterSet::Create() {
  	ParameterSet* object = new ParameterSet();
  	return static_cast<ParameterSet*>(GenerateId(object));
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  ParameterSet* ParameterSet::Create(const std::string& publicID) {
  	if ( PublicObject::IsRegistrationEnabled() && Find(publicID) != NULL ) {
  		SEISCOMP_ERROR(
  			"There exists already a PublicObject with Id '%s'",
  			publicID.c_str()
  		);
  		return NULL;
  	}
  
  	return new ParameterSet(publicID);
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  ParameterSet* ParameterSet::Find(const std::string& publicID) {
  	return ParameterSet::Cast(PublicObject::Find(publicID));
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::operator==(const ParameterSet& rhs) const {
  	if ( _baseID != rhs._baseID ) return false;
  	if ( _moduleID != rhs._moduleID ) return false;
  	if ( _created != rhs._created ) return false;
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::operator!=(const ParameterSet& rhs) const {
  	return !operator==(rhs);
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::equal(const ParameterSet& other) const {
  	return *this == other;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  void ParameterSet::setBaseID(const std::string& baseID) {
  	_baseID = baseID;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  const std::string& ParameterSet::baseID() const {
  	return _baseID;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  void ParameterSet::setModuleID(const std::string& moduleID) {
  	_moduleID = moduleID;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  const std::string& ParameterSet::moduleID() const {
  	return _moduleID;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  void ParameterSet::setCreated(const OPT(Seiscomp::Core::Time)& created) {
  	_created = created;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Seiscomp::Core::Time ParameterSet::created() const {
  	if ( _created )
  		return *_created;
  	throw Seiscomp::Core::ValueException("ParameterSet.created is not set");
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Config* ParameterSet::config() const {
  	return static_cast<Config*>(parent());
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  ParameterSet& ParameterSet::operator=(const ParameterSet& other) {
  	PublicObject::operator=(other);
  	_baseID = other._baseID;
  	_moduleID = other._moduleID;
  	_created = other._created;
  	return *this;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::assign(Object* other) {
  	ParameterSet* otherParameterSet = ParameterSet::Cast(other);
  	if ( other == NULL )
  		return false;
  
  	*this = *otherParameterSet;
  
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::attachTo(PublicObject* parent) {
  	if ( parent == NULL ) return false;
  
  	// check all possible parents
  	Config* config = Config::Cast(parent);
  	if ( config != NULL )
  		return config->add(this);
  
  	SEISCOMP_ERROR("ParameterSet::attachTo(%s) -> wrong class type", parent->className());
  	return false;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::detachFrom(PublicObject* object) {
  	if ( object == NULL ) return false;
  
  	// check all possible parents
  	Config* config = Config::Cast(object);
  	if ( config != NULL ) {
  		// If the object has been added already to the parent locally
  		// just remove it by pointer
  		if ( object == parent() )
  			return config->remove(this);
  		// The object has not been added locally so it must be looked up
  		else {
  			ParameterSet* child = config->findParameterSet(publicID());
  			if ( child != NULL )
  				return config->remove(child);
  			else {
  				SEISCOMP_DEBUG("ParameterSet::detachFrom(Config): parameterSet has not been found");
  				return false;
  			}
  		}
  	}
  
  	SEISCOMP_ERROR("ParameterSet::detachFrom(%s) -> wrong class type", object->className());
  	return false;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::detach() {
  	if ( parent() == NULL )
  		return false;
  
  	return detachFrom(parent());
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Object* ParameterSet::clone() const {
  	ParameterSet* clonee = new ParameterSet();
  	*clonee = *this;
  	return clonee;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::updateChild(Object* child) {
  	Parameter* parameterChild = Parameter::Cast(child);
  	if ( parameterChild != NULL ) {
  		Parameter* parameterElement
  			= Parameter::Cast(PublicObject::Find(parameterChild->publicID()));
  		if ( parameterElement && parameterElement->parent() == this ) {
  			*parameterElement = *parameterChild;
  			parameterElement->update();
  			return true;
  		}
  		return false;
  	}
  
  	Comment* commentChild = Comment::Cast(child);
  	if ( commentChild != NULL ) {
  		Comment* commentElement = comment(commentChild->index());
  		if ( commentElement != NULL ) {
  			*commentElement = *commentChild;
  			commentElement->update();
  			return true;
  		}
  		return false;
  	}
  
  	return false;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  void ParameterSet::accept(Visitor* visitor) {
  	if ( visitor->traversal() == Visitor::TM_TOPDOWN )
  		if ( !visitor->visit(this) )
  			return;
  
  	for ( std::vector<ParameterPtr>::iterator it = _parameters.begin(); it != _parameters.end(); ++it )
  		(*it)->accept(visitor);
  	for ( std::vector<CommentPtr>::iterator it = _comments.begin(); it != _comments.end(); ++it )
  		(*it)->accept(visitor);
  
  	if ( visitor->traversal() == Visitor::TM_BOTTOMUP )
  		visitor->visit(this);
  	else
  		visitor->finished();
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  size_t ParameterSet::parameterCount() const {
  	return _parameters.size();
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Parameter* ParameterSet::parameter(size_t i) const {
  	return _parameters[i].get();
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Parameter* ParameterSet::findParameter(const std::string& publicID) const {
  	for ( std::vector<ParameterPtr>::const_iterator it = _parameters.begin(); it != _parameters.end(); ++it )
  		if ( (*it)->publicID() == publicID )
  			return (*it).get();
  
  	return NULL;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::add(Parameter* parameter) {
  	if ( parameter == NULL )
  		return false;
  
  	// Element has already a parent
  	if ( parameter->parent() != NULL ) {
  		SEISCOMP_ERROR("ParameterSet::add(Parameter*) -> element has already a parent");
  		return false;
  	}
  
  	if ( PublicObject::IsRegistrationEnabled() ) {
  		Parameter* parameterCached = Parameter::Find(parameter->publicID());
  		if ( parameterCached ) {
  			if ( parameterCached->parent() ) {
  				if ( parameterCached->parent() == this )
  					SEISCOMP_ERROR("ParameterSet::add(Parameter*) -> element with same publicID has been added already");
  				else
  					SEISCOMP_ERROR("ParameterSet::add(Parameter*) -> element with same publicID has been added already to another object");
  				return false;
  			}
  			else
  				parameter = parameterCached;
  		}
  	}
  
  	// Add the element
  	_parameters.push_back(parameter);
  	parameter->setParent(this);
  
  	// Create the notifiers
  	if ( Notifier::IsEnabled() ) {
  		NotifierCreator nc(OP_ADD);
  		parameter->accept(&nc);
  	}
  
  	// Notify registered observers
  	childAdded(parameter);
  	
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::remove(Parameter* parameter) {
  	if ( parameter == NULL )
  		return false;
  
  	if ( parameter->parent() != this ) {
  		SEISCOMP_ERROR("ParameterSet::remove(Parameter*) -> element has another parent");
  		return false;
  	}
  
  	std::vector<ParameterPtr>::iterator it;
  	it = std::find(_parameters.begin(), _parameters.end(), parameter);
  	// Element has not been found
  	if ( it == _parameters.end() ) {
  		SEISCOMP_ERROR("ParameterSet::remove(Parameter*) -> child object has not been found although the parent pointer matches???");
  		return false;
  	}
  
  	// Create the notifiers
  	if ( Notifier::IsEnabled() ) {
  		NotifierCreator nc(OP_REMOVE);
  		(*it)->accept(&nc);
  	}
  
  	(*it)->setParent(NULL);
  	childRemoved((*it).get());
  	
  	_parameters.erase(it);
  
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::removeParameter(size_t i) {
  	// index out of bounds
  	if ( i >= _parameters.size() )
  		return false;
  
  	// Create the notifiers
  	if ( Notifier::IsEnabled() ) {
  		NotifierCreator nc(OP_REMOVE);
  		_parameters[i]->accept(&nc);
  	}
  
  	_parameters[i]->setParent(NULL);
  	childRemoved(_parameters[i].get());
  	
  	_parameters.erase(_parameters.begin() + i);
  
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  size_t ParameterSet::commentCount() const {
  	return _comments.size();
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Comment* ParameterSet::comment(size_t i) const {
  	return _comments[i].get();
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  Comment* ParameterSet::comment(const CommentIndex& i) const {
  	for ( std::vector<CommentPtr>::const_iterator it = _comments.begin(); it != _comments.end(); ++it )
  		if ( i == (*it)->index() )
  			return (*it).get();
  
  	return NULL;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::add(Comment* comment) {
  	if ( comment == NULL )
  		return false;
  
  	// Element has already a parent
  	if ( comment->parent() != NULL ) {
  		SEISCOMP_ERROR("ParameterSet::add(Comment*) -> element has already a parent");
  		return false;
  	}
  
  	// Duplicate index check
  	for ( std::vector<CommentPtr>::iterator it = _comments.begin(); it != _comments.end(); ++it ) {
  		if ( (*it)->index() == comment->index() ) {
  			SEISCOMP_ERROR("ParameterSet::add(Comment*) -> an element with the same index has been added already");
  			return false;
  		}
  	}
  
  	// Add the element
  	_comments.push_back(comment);
  	comment->setParent(this);
  
  	// Create the notifiers
  	if ( Notifier::IsEnabled() ) {
  		NotifierCreator nc(OP_ADD);
  		comment->accept(&nc);
  	}
  
  	// Notify registered observers
  	childAdded(comment);
  	
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::remove(Comment* comment) {
  	if ( comment == NULL )
  		return false;
  
  	if ( comment->parent() != this ) {
  		SEISCOMP_ERROR("ParameterSet::remove(Comment*) -> element has another parent");
  		return false;
  	}
  
  	std::vector<CommentPtr>::iterator it;
  	it = std::find(_comments.begin(), _comments.end(), comment);
  	// Element has not been found
  	if ( it == _comments.end() ) {
  		SEISCOMP_ERROR("ParameterSet::remove(Comment*) -> child object has not been found although the parent pointer matches???");
  		return false;
  	}
  
  	// Create the notifiers
  	if ( Notifier::IsEnabled() ) {
  		NotifierCreator nc(OP_REMOVE);
  		(*it)->accept(&nc);
  	}
  
  	(*it)->setParent(NULL);
  	childRemoved((*it).get());
  	
  	_comments.erase(it);
  
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::removeComment(size_t i) {
  	// index out of bounds
  	if ( i >= _comments.size() )
  		return false;
  
  	// Create the notifiers
  	if ( Notifier::IsEnabled() ) {
  		NotifierCreator nc(OP_REMOVE);
  		_comments[i]->accept(&nc);
  	}
  
  	_comments[i]->setParent(NULL);
  	childRemoved(_comments[i].get());
  	
  	_comments.erase(_comments.begin() + i);
  
  	return true;
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  bool ParameterSet::removeComment(const CommentIndex& i) {
  	Comment* object = comment(i);
  	if ( object == NULL ) return false;
  	return remove(object);
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  void ParameterSet::serialize(Archive& ar) {
  	// Do not read/write if the archive's version is higher than
  	// currently supported
  	if ( ar.isHigherVersion<0,11>() ) {
  		SEISCOMP_ERROR("Archive version %d.%d too high: ParameterSet skipped",
  		               ar.versionMajor(), ar.versionMinor());
  		ar.setValidity(false);
  		return;
  	}
  
  	PublicObject::serialize(ar);
  	if ( !ar.success() ) return;
  
  	ar & NAMED_OBJECT_HINT("baseID", _baseID, Archive::XML_ELEMENT);
  	ar & NAMED_OBJECT_HINT("moduleID", _moduleID, Archive::XML_ELEMENT);
  	ar & NAMED_OBJECT_HINT("created", _created, Archive::SPLIT_TIME);
  	if ( ar.hint() & Archive::IGNORE_CHILDS ) return;
  	ar & NAMED_OBJECT_HINT("parameter",
  	                       Seiscomp::Core::Generic::containerMember(_parameters,
  	                       Seiscomp::Core::Generic::bindMemberFunction<Parameter>(static_cast<bool (ParameterSet::*)(Parameter*)>(&ParameterSet::add), this)),
  	                       Archive::STATIC_TYPE);
  	ar & NAMED_OBJECT_HINT("comment",
  	                       Seiscomp::Core::Generic::containerMember(_comments,
  	                       Seiscomp::Core::Generic::bindMemberFunction<Comment>(static_cast<bool (ParameterSet::*)(Comment*)>(&ParameterSet::add), this)),
  	                       Archive::STATIC_TYPE);
  }
  // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  
  
  
  
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  }
  }
  