module UniverseCompiler module Universe module Duplication def dup UniverseCompiler.logger.debug "Starting '#{name}' universe duplication" duplicated_universe = build_duplicated_universe_with_references duplicated_universe.resolve_entities_reference raise UniverseCompiler::Error, "Compilation error: Generated universe '#{duplicated_universe.name}' is invalid!" unless duplicated_universe.valid? UniverseCompiler.logger.debug "Completed '#{name}' universe duplication" duplicated_universe end protected def resolve_entities_reference entities.map!(&:resolve_fields_references!) self end private def duplicate_entities(target_universe = nil) entities.map do |entity| debug_msg = "Duplicating '#{entity.to_composite_key}' from universe '#{self.name}'" debug_msg += " to universe '#{target_universe.name}'" unless target_universe.nil? UniverseCompiler.logger.debug debug_msg fields = Marshal::load(Marshal.dump entity).fields fields[:name] = entity.name if entity.class.auto_named_entity_type? entity_copy = entity.class.new fields: fields, universe: target_universe deep_map entity_copy.fields do |leaf| case leaf when UniverseCompiler::Entity::Base # All entities are supposed to be now references instead after the Marshall dump/load process raise UniverseCompiler::Error, 'Should never happen!!' when UniverseCompiler::Entity::Reference leaf.universe = target_universe else raise UniverseCompiler::Error, 'Should never happen too!!' if leaf.respond_to? :universe leaf end end target_universe.add entity_copy unless target_universe.nil? end end def build_duplicated_universe_with_references target_name = '%s - COMPILED #%s' % [name, '%s'] duplicated_universe = self.class.new target_name duplicated_universe.compiled = true duplicated_universe.name = duplicated_universe.name % [duplicated_universe.object_id] UniverseCompiler.logger.debug "Generating new universe '#{duplicated_universe.name}'." duplicate_entities duplicated_universe duplicated_universe end end end end