aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stif/codif_line_synchronization.rb
blob: deadad5ba065818a5db8b6a106b850132ad40503 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
module Stif
  module CodifLineSynchronization
    class << self
      def synchronize
        start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
        # Fetch Codifline data
        client = Codifligne::API.new
        operators       = client.operators
        lines           = client.lines
        networks        = client.networks
        # groups_of_lines = client.groups_of_lines

        Rails.logger.info "Codifligne:sync - Codifligne request processed in #{elapsed_time_since start_time} seconds"

        # Create or update Companies
        stime = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
        operators.map       { |o| create_or_update_company(o) }
        log_create_or_update "Companies", operators.count, stime

        # Create or update Lines
        stime = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
        lines.map           { |l| create_or_update_line(l) }
        log_create_or_update "Lines", lines.count, stime

        # Create or update Networks
        stime = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
        networks.map        { |n| create_or_update_network(n) }
        log_create_or_update "Networks", networks.count, stime

        # # Create or update Group of lines
        # stime = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
        # groups_of_lines.map { |g| create_or_update_group_of_lines(g) }
        # log_create_or_update "Group of lines", groups_of_lines.count, stime

        # # Delete deprecated Group of lines
        # deleted_gr = delete_deprecated(groups_of_lines, Chouette::GroupOfLine)
        # log_deleted "Group of lines", deleted_gr unless deleted_gr == 0

        # Delete deprecated Networks
        deleted_ne = delete_deprecated(networks, Chouette::Network)
        log_deleted "Networks", deleted_ne unless deleted_ne == 0

        # Delete deprecated Lines
        deleted_li = delete_deprecated_lines(lines)
        log_deleted "Lines", deleted_li unless deleted_li == 0

        # Delete deprecated Operators
        deleted_op = delete_deprecated(operators, Chouette::Company)
        log_deleted "Operators", deleted_op unless deleted_op == 0
        {
          imported: operators.count + lines.count + networks.count,
          deleted: deleted_op + deleted_li + deleted_ne
        }
      end

      def create_or_update_company(api_operator)
        params = {
          name: api_operator.name,
          objectid: api_operator.stif_id,
          import_xml: api_operator.xml
        }
        save_or_update(params, Chouette::Company)
      end

      def create_or_update_line(api_line)
        params = {
          name: api_line.name,
          objectid: api_line.stif_id,
          number: api_line.short_name,
          deactivated: (api_line.status == "inactive" ? true : false),
          import_xml: api_line.xml
        }

        params[:transport_submode] = api_line.transport_submode.to_s
        unless api_line.operator_ref.nil?
          params[:company] = Chouette::Company.find_by(objectid: api_line.operator_ref)
        end
        save_or_update(params, Chouette::Line)
      end

      def create_or_update_network(api_network)
        params = {
          name: api_network.name,
          objectid: api_network.stif_id,
          import_xml: api_network.xml
        }

        # Find Lines
        params[:lines] = []
        api_network.line_codes.each do |line|
          line_id = "STIF:CODIFLIGNE:Line:" + line
          chouette_line = Chouette::Line.find_by(objectid: line_id)
          params[:lines] << chouette_line if chouette_line.present?
        end

        save_or_update(params, Chouette::Network)
      end

      def create_or_update_group_of_lines(api_group_of_lines)
        params = {
          name: api_group_of_lines.name,
          objectid: api_group_of_lines.stif_id,
          import_xml: api_group_of_lines.xml
        }

        # Find Lines
        params[:lines] = []
        api_group_of_lines.line_codes.each do |line|
          line_id = "STIF:CODIFLIGNE:Line:" + line
          # TODO : handle when lines doesn't exist
          chouette_line = Chouette::Line.find_by(objectid: line_id)
          params[:lines] << chouette_line if chouette_line.present?
        end

        save_or_update(params, Chouette::GroupOfLine)
      end

      def delete_deprecated(objects, klass)
        ids = objects.map{ |o| o.stif_id }.to_a
        deprecated = klass.where.not(objectid: ids)
        deprecated.destroy_all.length
      end

      def delete_deprecated_lines(lines)
        ids = lines.map{ |l| l.stif_id }.to_a
        deprecated = Chouette::Line.where.not(objectid: ids).where(deactivated: false)
        deprecated.update_all deactivated: true
      end

      def save_or_update(params, klass)
        params[:line_referential] = LineReferential.first
        object = klass.where(objectid: params[:objectid]).first
        if object
          object.assign_attributes(params)
          object.save if object.changed?
        else
          object = klass.new(params)
          object.save if object.valid?
        end
        object
      end

      def elapsed_time_since start_time = 0
        Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) - start_time
      end

      def log_create_or_update name, count, start_time
        time = elapsed_time_since start_time
        Rails.logger.info "Codifligne:sync - #{count} #{name} retrieved"
        Rails.logger.info "Codifligne:sync - Create or update #{name} done in #{time} seconds"
      end

      def log_deleted name, count
        Rails.logger.info "Codifligne:sync - #{count} #{name} deleted"
      end
    end
  end
end