Browse code

mlt: neu entwickelt und funktioniert grandios

git-svn-id: svn://devel.enda.eu/svnroot/e_kommu/xml_export/trunk@1008 6d5695c6-a2e0-438d-8b37-c93c90bbf000

Matthias Lüttgert authored on 24/06/2016 17:55:45
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,260 @@
0
+# -*- coding: utf-8 -*-
1
+#
2
+# xml_art15_checker.rb
3
+# (c) ENDA, 2016
4
+# 
5
+# by mlt
6
+#
7
+# Rel-0-0-1
8
+# 2016-06-24, mlt
9
+
10
+class Art15_XML_Checker
11
+  attr :glade
12
+
13
+  def initialize(glade, art15_xml_datei)
14
+    @glade = glade
15
+    @art15_xml_datei = art15_xml_datei
16
+    @file_num_lines = 0
17
+    @bar = @glade['progressbar1']
18
+    self.pulse
19
+    @odoc = nil
20
+    @oroot = nil
21
+    @dbh = nil
22
+    # Einziger Method-Call von außen: export, s.u.
23
+  end
24
+
25
+  def pulse
26
+    @bar.pulse
27
+    Gtk.main_iteration
28
+  end
29
+
30
+  # check_dp2tp_links
31
+  #   → valdoc    : Ein XML-Dokument als gnome-libxml2-Objekt
32
+  #   ← alles_gut : Boolean true, wenn alle TPs vorhanden, sonst false
33
+  #
34
+  #   Sammelt alle Einleitstellen und deren Links auf die Kläranlage
35
+  #   und prüft, ob eine solche Kläranlage im Dokument vorhanden ist
36
+  #   und erzeugt dabei Konsolausgaben (✔ Treffer bzw. ✘ FEHLT!).
37
+  #
38
+  def check_dp2tp_links(valdoc)
39
+    # Erstmal die DPs finden
40
+    # Dann über die iterieren
41
+      # In jedem DP den Zeiger auf die TP finden
42
+      # Prüfen, ob das Dokument diese TP enthält
43
+      # Dabei schöne Meldungen herausgeben
44
+    alles_gut = true
45
+    # Erstmal die DPs finden
46
+    root = valdoc.root
47
+    if dps = root.find_first('/UWWTD_Data/UWWTD_Report/DischargePoints')
48
+      # Dann über die iterieren
49
+      dps.each_element do |dp|
50
+        # In jedem DP den Zeiger auf die TP finden
51
+        dcp_code = dp.find_first("dd823:dcpCode")
52
+        uww_code = dp.find_first("dd823:uwwCode")
53
+        print "Link von <#{dcp_code.content}> auf <#{uww_code.content}>: "
54
+        # Prüfen, ob das Dokument diese TP enthält
55
+        xpath = "/UWWTD_Data/UWWTD_Report/UWWTPs/UWWTP[dd821:uwwCode=\"#{uww_code.content}\"]"
56
+        # Dabei schöne Meldungen herausgeben
57
+        if tps = root.find_first(xpath)
58
+          puts "✔ Treffer"
59
+        else
60
+          puts "✘ FEHLT!"
61
+          alles_gut = false
62
+        end
63
+      end
64
+    end
65
+    return alles_gut
66
+  end
67
+
68
+  def check_dp2tp_links_with_schema
69
+    @bar.pulse_step = 0.07
70
+    @bar.fraction = 0.0
71
+    @bar.text="checking dp2tp links..."
72
+    puts "Start am/um #{Stnd.now}"
73
+    self.pulse
74
+    valdoc = XML::Document.file(@art15_xml_datei)
75
+    # result_schema_check = check_against_schema(valdoc)
76
+    result_dp2tp_links_check = check_dp2tp_links(valdoc)
77
+    @bar.text="done"
78
+    @bar.fraction = 1.0
79
+    puts "Ende am/um #{Stnd.now}"
80
+  end
81
+
82
+  def check_against_schema(valdoc)
83
+    schema_document = XML::Document.file('../schemata/UWWTD_Art15.xsd')
84
+    schema = XML::Schema.document(schema_document)
85
+    STDOUT.flush
86
+    STDERR.flush
87
+    begin
88
+      result = valdoc.validate_schema(schema) do |message, is_error|
89
+        # Das kann man sich getrost in die Haare reiben, denn validate_schema schmeißt eine Exception...
90
+        if is_error
91
+          puts "ERROR!"
92
+        else
93
+          puts "WARNING!"
94
+        end
95
+        puts "Anfang der Meldung:"
96
+        puts message
97
+        puts "Ende der Meldung."
98
+      end
99
+    rescue Exception => wumm
100
+      pulse
101
+      puts "Exception <#{wumm}>."
102
+      # print wumm.backtrace.join("\n")
103
+      puts
104
+    end
105
+    if result
106
+      puts "Das Dokument ist bzgl. des Schemas perfekt"
107
+    else
108
+      puts "Das Dokument kann noch besser werden"
109
+    end
110
+    pulse
111
+    return result
112
+  end
113
+
114
+
115
+  def fill_dp(dp_node, dp_row)
116
+    dp_node << state = XML::Node.new('dd823:dcpState')
117
+    active = true
118
+    active_text = "aktiv und berichtet"
119
+    active_flag = 1
120
+    if dp_row['dp_state_active'] == 0
121
+      active = false
122
+      active_text = "aktiv und berichtet"
123
+      active_flag = 0
124
+    elsif dp_row['dp_to_be_reported'] == 0
125
+      active = false
126
+      active_text = "aktiv und berichtet"
127
+      active_flag = 2
128
+    end
129
+    state << active_flag
130
+    
131
+    dp_node << rep_code = XML::Node.new('dd823:repCode')
132
+    rep_code << REP_CODE
133
+    
134
+    fill_node( dp_node, dp_row, 'pl_eu_key', 'dd823:uwwCode')
135
+    if !dp_row['pl_eu_key']
136
+      puts "FEHLER: DP #{dp_row['dp_eu_key']} aus Land #{dp_row['federal_state_id']} hat keinen pl_eu_key!!!!!!!!!!!!!"
137
+    end
138
+    
139
+    fill_node( dp_node, dp_row, 'dp_eu_key', 'dd823:dcpCode')
140
+    fill_node( dp_node, dp_row, 'dp_name', 'dd823:dcpName')
141
+    fill_node( dp_node, dp_row, 'nuts', 'dd823:dcpNUTS')
142
+
143
+    if dp_row['dp_eu_lat']
144
+      dp_node << latitude = XML::Node.new('dd823:dcpLatitude')
145
+      latitude << sprintf("%.6e", dp_row['dp_eu_lat']).to_f.to_s
146
+    end
147
+    if dp_row['dp_eu_long']
148
+      dp_node << longitude = XML::Node.new('dd823:dcpLongitude')
149
+      longitude << sprintf("%.6e", dp_row['dp_eu_long']).to_f.to_s
150
+    end
151
+    
152
+    # dcpWaterBodyType:
153
+    if dp_row['dp_surface_sp_id']
154
+      # dp.dp_surface_sp_id <--> l_waters.id
155
+      # l_waters hält leider nicht die EU-Schlüssel, daher müssen wir low-level auf der id arbeiten
156
+      wbt_key = case dp_row['dp_surface_sp_id']
157
+                when 1 then 'LF' # Land
158
+                when 2 then 'FW' # Süßwasser
159
+                when 3 then 'ES' # Ästuar
160
+                when 4 then 'CW' # Küste
161
+                else raise Exception.new, "ERROR: xml_art15_exporter.rb, fill_dp, case dp_surface_sp_id: else reached"
162
+                end
163
+      poke(dp_node, wbt_key, 'dd823:dcpWaterBodyType')
164
+      # dcpIrrigation:
165
+      if dp_row['dp_surface_sp_id'] == 1
166
+        if dp_row['dp_surface_land_id']
167
+          irrigation_key = case dp_row['surface_land_key']
168
+                           when 'BEWAESSERUNG' then 'IR' # Irrigation
169
+                           when 'INFILTRATION' then 'IN' # Infiltration
170
+                           when 'SONSTIGE' then 'OT' # Other
171
+                           else raise Exception.new, "ERROR: xml_art15_exporter.rb, fill_dp, case surface_land_key: else reached"
172
+                           end
173
+          poke(dp_node, irrigation_key, 'dd823:dcpIrrigation')
174
+        else
175
+          puts "FEHLER: Land #{dp_row['federal_state_id']}, dp #{dp_row['dp_name']} (#{dp_row['dp_key']}) hat keine dp_surface_land_id, obwohl die Einleitung in Land erfolgt (Versickerung)"
176
+        end
177
+      end
178
+    else
179
+      puts "FEHLER: Land #{dp_row['federal_state_id']}, dp #{dp_row['dp_name']} (#{dp_row['dp_key']}), active = #{active ? "1" : "0"}, hat keine dp_surface_sp_id. dcpWaterBodyType kann nicht gefüllt werden!"
180
+    end
181
+    
182
+    poke(dp_node, 'A54', 'dd823:dcpTypeOfReceivingArea')
183
+    # TODO: Evtl. hier Ziffernkombi statt DE
184
+    poke(dp_node, 'DE', 'dd823:rcaCode') # Das ist die ID, die oben für die Receiving Area Deutschland hartcodiert vergeben wurde
185
+    fill_node_10(dp_node, dp_row, 'dp_surface', 'dd823:dcpSurfaceWaters')
186
+    fill_node(dp_node, dp_row, 'water_body_eu_key', 'dd823:dcpWaterbodyID')
187
+    
188
+    # Nur bei Versickerung:
189
+    if dp_row['dp_surface_sp_id'] && dp_row['dp_surface_sp_id'] == 1
190
+      if dp_row['dp_gwbody_id'] && dp_row['groundwater_body_eu_key']
191
+        fill_node(dp_node, dp_row, 'groundwater_body_eu_key', 'dd823:dcpGroundWater')
192
+      else
193
+        if active then
194
+          puts "FEHLER: Land #{dp_row['federal_state_id']}, dp #{dp_row['dp_name']} (#{active_text}, #{dp_row['dp_key']}) hat keine dp_gwbody_id oder referenziert keinen derzeit gültigen Grundwasserkörper, obwohl die Einleitung in Land erfolgt (Versickerung)"
195
+        end
196
+      end
197
+    end
198
+
199
+    # dcpReceivingWater : rw_wise_key fehlt
200
+
201
+    if dp_row['wrrl_sub_unit_description']
202
+      wrrl_sub_unit_key = /^[0-9_]+/u.match(dp_row['wrrl_sub_unit_description'])
203
+      poke(dp_node, wrrl_sub_unit_key, 'dd823:dcpWFDSubUnit')
204
+    end
205
+
206
+    fill_node(dp_node, dp_row, 'river_basin_district_eu_key', 'dd823:dcpWFDRBD')
207
+    fill_node(dp_node, dp_row, 'dp_remark', 'dd823:dcpRemarks')
208
+  end
209
+  
210
+
211
+  def create_discharge_points
212
+    @bar.text="discharge points..."
213
+    dps = XML::Node.new('DischargePoints')
214
+    stmt = "select dp.*, p.pl_eu_key, lrc.key as nuts, lus.key as surface_land_key,
215
+        lwb.eu_key as water_body_eu_key, lgwb.eu_key as groundwater_body_eu_key,
216
+        lsu.description as wrrl_sub_unit_description, lrbd.river_basin_district_eu_key
217
+      from discharge_points dp
218
+        left join plants p
219
+          on dp.plant_id = p.id
220
+        left join l_region_code lrc
221
+          on dp.dp_nuts_id = lrc.id
222
+          and lrc.state = 0
223
+        left join l_usage lus
224
+          on dp.dp_surface_land_id = lus.id
225
+          and lus.state = 0
226
+        left join l_water_body_code lwb
227
+          on dp.dp_waterbody_id = lwb.id
228
+        left join l_groundwater_body lgwb
229
+          on dp.dp_gwbody_id = lgwb.id
230
+        left join l_wrrl_sub_units lsu
231
+          on dp.dp_su_id = lsu.id
232
+        left join l_river_basin_districts lrbd
233
+          on dp.rb_rbd_id = lrbd.id
234
+      where dp.state = 0
235
+        and dp.date_from = #{DATE_FROM}
236
+        and dp.federal_state_id < 17
237
+      order by dp.federal_state_id, dp.dp_eu_key"
238
+    print "SQL-Statement läuft ... #{Stnd.now}\n"
239
+    sth = dbh.execute(stmt)
240
+    pulse
241
+    print "SQL-Statement fertig    #{Stnd.now}\n"
242
+    counter = 0
243
+    sth.fetch do |row|
244
+      counter += 1
245
+      dps << dp = XML::Node.new('DischargePoint')
246
+      fill_dp(dp, row)
247
+      if counter % 100 == 0
248
+        pulse
249
+        print "."
250
+        STDOUT.flush
251
+      end
252
+      break if $testrun && counter >= 25
253
+    end
254
+    print "\n"
255
+    puts "\n#{counter} Discharge Points geschrieben\n"
256
+    return dps
257
+  end
258
+
259
+end