module Maestrano::Connector::Rails class ComplexEntity @@external_name = External.external_name # ------------------------------------------------------------- # Complex specific methods # Those methods needs to be implemented in each complex entity # ------------------------------------------------------------- def connec_entities_names raise "Not implemented" end def external_entities_names raise "Not implemented" end # input : { # connec_entities_names[0]: [unmapped_connec_entitiy1, unmapped_connec_entitiy2], # connec_entities_names[1]: [unmapped_connec_entitiy3, unmapped_connec_entitiy4] # } # output : { # connec_entities_names[0]: { # external_entities_names[0]: [unmapped_connec_entitiy1, unmapped_connec_entitiy2] # }, # connec_entities_names[1]: { # external_entities_names[0]: [unmapped_connec_entitiy3], # external_entities_names[1]: [unmapped_connec_entitiy4] # } # } def connec_model_to_external_model(connec_hash_of_entities) raise "Not implemented" end # input : { # external_entities_names[0]: [unmapped_external_entity1}, unmapped_external_entity2], # external_entities_names[1]: [unmapped_external_entity3}, unmapped_external_entity4] # } # output : { # external_entities_names[0]: { # connec_entities_names[0]: [unmapped_external_entity1], # connec_entities_names[1]: [unmapped_external_entity2] # }, # external_entities_names[1]: { # connec_entities_names[0]: [unmapped_external_entity3, unmapped_external_entity4] # } # } def external_model_to_connec_model(external_hash_of_entities) raise "Not implemented" end # ------------------------------------------------------------- # General methods # ------------------------------------------------------------- def map_to_external_with_idmap(entity, organization, connec_entity_name, external_entity_name, sub_entity_instance) idmap = IdMap.find_by(connec_id: entity['id'], connec_entity: connec_entity_name.downcase, external_entity: external_entity_name.downcase, organization_id: organization.id) if idmap && idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at'] ConnectorLogger.log('info', organization, "Discard Connec! #{connec_entity_name} : #{entity}") nil else {entity: sub_entity_instance.map_to(external_entity_name, entity, organization), idmap: idmap || IdMap.create(connec_id: entity['id'], connec_entity: connec_entity_name.downcase, external_entity: external_entity_name.downcase, organization_id: organization.id, name: sub_entity_instance.object_name_from_connec_entity_hash(entity))} end end # ------------------------------------------------------------- # Entity equivalent methods # ------------------------------------------------------------- def get_connec_entities(client, last_synchronization, organization, opts={}) entities = ActiveSupport::HashWithIndifferentAccess.new self.connec_entities_names.each do |connec_entity_name| sub_entity_instance = "Entities::SubEntities::#{connec_entity_name.titleize.split.join}".constantize.new entities[connec_entity_name] = sub_entity_instance.get_connec_entities(client, last_synchronization, organization, opts) end entities end def get_external_entities(client, last_synchronization, organization, opts={}) entities = ActiveSupport::HashWithIndifferentAccess.new self.external_entities_names.each do |external_entity_name| sub_entity_instance = "Entities::SubEntities::#{external_entity_name.titleize.split.join}".constantize.new entities[external_entity_name] = sub_entity_instance.get_external_entities(client, last_synchronization, organization, opts) end entities end def consolidate_and_map_data(connec_entities, external_entities, organization, opts) modeled_external_entities = external_model_to_connec_model(external_entities) modeled_connec_entities = connec_model_to_external_model(connec_entities) modeled_external_entities.each do |external_entity_name, entities_in_connec_model| entities_in_connec_model.each do |connec_entity_name, entities| sub_entity_instance = "Entities::SubEntities::#{external_entity_name.titleize.split.join}".constantize.new entities.map!{|entity| idmap = IdMap.find_by(external_id: sub_entity_instance.get_id_from_external_entity_hash(entity), external_entity: external_entity_name.downcase, connec_entity: connec_entity_name.downcase, organization_id: organization.id) # No idmap: creating one, nothing else to do unless idmap next {entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: IdMap.create(external_id: sub_entity_instance.get_id_from_external_entity_hash(entity), external_entity: external_entity_name.downcase, connec_entity: connec_entity_name.downcase, organization_id: organization.id, name: sub_entity_instance.object_name_from_external_entity_hash(entity))} end # Entity has not been modified since its last push to connec! if idmap.last_push_to_connec && idmap.last_push_to_connec > sub_entity_instance.get_last_update_date_from_external_entity_hash(entity) ConnectorLogger.log('info', organization, "Discard #{@@external_name} #{external_entity_name} : #{entity}") next nil end equivalent_connec_entities = connec_entities[connec_entity_name][external_entity_name] || [] # Check for conflict with entities from connec! if idmap.connec_id && connec_entity = equivalent_connec_entities.detect{|connec_entity| connec_entity['id'] == idmap.connec_id} # We keep the most recently updated entity if !opts[:connec_preemption].nil? keep_external = !opts[:connec_preemption] else keep_external = connec_entity['updated_at'] < sub_entity_instance.get_last_update_date_from_external_entity_hash(entity) end if keep_external ConnectorLogger.log('info', organization, "Conflict between #{@@external_name} #{external_entity_name} #{entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from #{@@external_name} kept") equivalent_connec_entities.delete(connec_entity) {entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: idmap} else ConnectorLogger.log('info', organization, "Conflict between #{@@external_name} #{external_entity_name} #{entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from Connec! kept") nil end else {entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: idmap} end }.compact! end end modeled_connec_entities.each do |connec_entity_name, entities_in_external_model| entities_in_external_model.each do |external_entity_name, entities| sub_entity_instance = "Entities::SubEntities::#{connec_entity_name.titleize.split.join}".constantize.new entities.map!{|entity| self.map_to_external_with_idmap(entity, organization, connec_entity_name, external_entity_name, sub_entity_instance) }.compact! end end return {connec_entities: modeled_connec_entities, external_entities: modeled_external_entities} end # input : { # external_entities_names[0]: { # connec_entities_names[0]: [mapped_external_entity1], # connec_entities_names[1]: [mapped_external_entity2] # }, # external_entities_names[1]: { # connec_entities_names[0]: [mapped_external_entity3, mapped_external_entity4] # } # } def push_entities_to_connec(connec_client, mapped_external_entities_with_idmaps, organization) mapped_external_entities_with_idmaps.each do |external_entity_name, entities_in_connec_model| sub_entity_instance = "Entities::SubEntities::#{external_entity_name.titleize.split.join}".constantize.new entities_in_connec_model.each do |connec_entity_name, mapped_entities_with_idmaps| sub_entity_instance.push_entities_to_connec_to(connec_client, mapped_entities_with_idmaps, connec_entity_name, organization) end end end def push_entities_to_external(external_client, mapped_connec_entities_with_idmaps, organization) mapped_connec_entities_with_idmaps.each do |connec_entity_name, entities_in_external_model| sub_entity_instance = "Entities::SubEntities::#{connec_entity_name.titleize.split.join}".constantize.new entities_in_external_model.each do |external_entity_name, mapped_entities_with_idmaps| sub_entity_instance.push_entities_to_external_to(external_client, mapped_entities_with_idmaps, external_entity_name, organization) end end end end end