module UniverseCompiler module Universe module Entities def empty? entities.empty? end def add(entity) raise UniverseCompiler::Error, 'An entity cannot be null !' if entity.nil? raise UniverseCompiler::Error, 'An entity must have a name !' unless entity.respond_to? :name raise UniverseCompiler::Error, 'An entity must have a name !' if entity.name.nil? or entity.name.empty? unless UniverseCompiler::Entity::TypeManagement.valid_for_type? entity entity.extend UniverseCompiler::Entity::TypeManagement end raise UniverseCompiler::Error, "An entity named '#{entity.name}' already exists with the type '#{entity.type}' !" if by_uniq_key.keys.include? [entity.type, entity.name] raise UniverseCompiler::Error, 'Invalid type specified' if entity.type.nil? raise UniverseCompiler::Error, 'Type cannot contain spaces' if entity.type =~ /\s/ # Normally here the entity is valid # We add it to the universe and index it entities << entity if entity.respond_to? :'universe=' entity.universe = self end index entity entity end def <<(entity) add entity self end def delete(entity) # Remove references to entity impacted_entities = {} entities.each do |e| e.class.fields_constraints.each do |field_name, constraints| if constraints.keys.include? :has_one if e[field_name] == entity e[field_name] = nil impacted_entities[e] ||= [] impacted_entities[e] << field_name end end if constraints.keys.include? :has_many if e[field_name].include? entity e[field_name].delete entity impacted_entities[e] ||= [] impacted_entities[e] << field_name unless impacted_entities[e].include? field_name end end end end # Then delete the entity entities.delete entity entity.universe = nil if entity.respond_to? :'universe=' reindex_all entities unless impacted_entities.empty? UniverseCompiler.logger.warn "Impacts of '#{entity.as_path}' deletion:" impacted_entities.each do |k, v| UniverseCompiler.logger.warn " - '#{k.as_path}' fields : #{v.join ', '}" end end impacted_entities end def replace(entity, by) raise UniverseCompiler::Error, "Wrong type, cannot replace '#{entity.as_path}' by '#{by.as_path}' !" unless entity.type == by.type raise UniverseCompiler::Error, "Cannot replace '#{entity.as_path}' with '#{by.as_path}' which is alreadyin the universe!" if entity.universe == by.universe # Change references to entity impacted_entities = {} entities.each do |e| e.class.fields_constraints.each do |field_name, constraints| if constraints.keys.include? :has_one if e[field_name] == entity e[field_name] = by impacted_entities[e] ||= [] impacted_entities[e] << field_name end end if constraints.keys.include? :has_many if e[field_name].map! do |entity_list_item| if (entity == entity_list_item) impacted_entities[e] ||= [] impacted_entities[e] << field_name unless impacted_entities[e].include? field_name by else entity_list_item end end end end end end # Then replace the entity entities[entities.index(entity)] = by entity.universe = nil if entity.respond_to? :'universe=' by.universe = self if by.respond_to? :'universe=' reindex_all entities unless impacted_entities.empty? UniverseCompiler.logger.warn "Impacts of '#{entity.as_path}' deletion:" impacted_entities.each do |k, v| UniverseCompiler.logger.warn " - '#{k.as_path}' fields : #{v.join ', '}" end end impacted_entities end def clear entities.each { |e| e.universe = nil } entities.clear clear_indices end private attr_reader :entities end end end