bcl 0.1.9 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/bcl.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'bcl/component_spreadsheet'
2
2
  require 'bcl/component_xml'
3
3
  require 'bcl/component_methods'
4
+ require 'bcl/measure_xml'
5
+ require 'bcl/bcl_xml'
4
6
  require 'bcl/tar_ball'
5
7
  require 'bcl/master_taxonomy'
6
8
  require 'bcl/mongo_to_component'
@@ -0,0 +1,130 @@
1
+ require 'uuid' # gem install uuid
2
+
3
+ module BCL
4
+ ProvStruct = Struct.new(:author, :datetime, :comment)
5
+ TagsStruct = Struct.new(:descriptor)
6
+ AttrStruct = Struct.new(:name, :value, :datatype, :units)
7
+ FileStruct = Struct.new(:version_software_program, :version_id, :fqp_file, :filename, :filetype, :usage_type, :checksum)
8
+ CostStruct = Struct.new(:cost_name, :cost_type, :category, :value, :interval,
9
+ :interval_units, :year, :location, :units, :currency, :source,
10
+ :reference_component_name, :reference_component_id)
11
+
12
+ ObjectStruct = Struct.new(:obj_type, :obj_instance)
13
+
14
+ class BaseXml
15
+ attr_accessor :name
16
+ attr_accessor :description
17
+ attr_accessor :uuid
18
+ attr_accessor :vuid
19
+
20
+ attr_accessor :attributes
21
+ attr_accessor :files
22
+ attr_accessor :costs
23
+ attr_accessor :tags
24
+ attr_accessor :provenances
25
+
26
+ def initialize(save_path)
27
+ @name = "" #this is also a unique identifier to the component...
28
+ @description = ""
29
+
30
+ @provenances = []
31
+ @tags = []
32
+ @attributes = []
33
+ @files = []
34
+
35
+ @schema_url = "schema.xsd"
36
+ end
37
+
38
+ def generate_uuid()
39
+ @uuid = UUID.new.generate
40
+ end
41
+
42
+ def generate_vuid()
43
+ @vuid = UUID.new.generate
44
+ end
45
+
46
+
47
+ def add_provenance(author, datetime, comment)
48
+ prov = ProvStruct.new
49
+ prov.author = author
50
+ prov.datetime = datetime
51
+ prov.comment = comment
52
+
53
+ @provenances << prov
54
+ end
55
+
56
+ def add_tag(tag_name)
57
+ tag = TagsStruct.new
58
+ tag.descriptor = tag_name
59
+
60
+ @tags << tag
61
+ end
62
+
63
+ def add_attribute(name, value, units, datatype = nil)
64
+ attr = AttrStruct.new
65
+ attr.name = name
66
+ attr.value = value
67
+
68
+ if !datatype.nil?
69
+ attr.datatype = datatype
70
+ else
71
+ attr.datatype = get_datatype(value)
72
+ end
73
+ attr.units = units
74
+
75
+ @attributes << attr
76
+ end
77
+
78
+ def add_file(version_sp, version_id, fqp_file, filename, filetype, usage_type = nil, checksum = nil)
79
+ fs = FileStruct.new
80
+ fs.version_software_program = version_sp
81
+ fs.version_id = version_id
82
+ fs.fqp_file = fqp_file
83
+ fs.filename = filename
84
+ fs.filetype = filetype
85
+ fs.usage_type = usage_type if usage_type != nil
86
+ fs.checksum = checksum if checksum != nil
87
+
88
+ @files << fs
89
+ end
90
+
91
+ #return the title case of the string
92
+ def tc(input)
93
+ val = input.gsub(/\b\w/){$&.upcase}
94
+ if val.downcase == "energyplus"
95
+ val = "EnergyPlus"
96
+ end
97
+ return val
98
+ end
99
+
100
+ def get_attribute(attribute_name)
101
+ result = nil
102
+ @attributes.each do |attr|
103
+ if attr.name == attribute_name
104
+ result = attr
105
+ end
106
+ end
107
+
108
+ result
109
+ end
110
+
111
+ def get_datatype(input_value)
112
+ dt = 'undefined'
113
+
114
+ # simple method to test if the input_value is a string, float, or integer.
115
+ # First convert the value back to a string for testing (in case it was passed as a float/integer)
116
+ test = input_value.to_s
117
+ input_value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
118
+
119
+ if input_value.is_a?(Fixnum) || input_value.is_a?(Bignum)
120
+ dt = "int"
121
+ elsif input_value.is_a?(Float)
122
+ dt = "float"
123
+ else
124
+ dt = "string"
125
+ end
126
+
127
+ dt
128
+ end
129
+ end
130
+ end
@@ -39,6 +39,7 @@ module BCL
39
39
  def initialize()
40
40
  @config = nil
41
41
  @session = nil
42
+ @api_version = 2.0
42
43
  config_path = File.expand_path('~') + '/.bcl'
43
44
  config_name = 'config.yml'
44
45
  if File.exists?(config_path + "/" + config_name)
@@ -79,6 +80,7 @@ module BCL
79
80
  session_name = res_j["session_name"]
80
81
 
81
82
  @session = { session_name => sessid }
83
+
82
84
  end
83
85
 
84
86
  res
@@ -88,7 +90,7 @@ module BCL
88
90
  # pushes component to the bcl and sets to published (for now). Username and password and
89
91
  # set in ~/.bcl/config.yml file which determines the permissions and the group to which
90
92
  # the component will be uploaded
91
- def push_component(filename_and_path, write_receipt_file)
93
+ def push_content(filename_and_path, write_receipt_file, content_type)
92
94
  raise "Please login before pushing components" if @session.nil?
93
95
 
94
96
  valid = false
@@ -96,36 +98,24 @@ module BCL
96
98
  filename = File.basename(filename_and_path)
97
99
  filepath = File.dirname(filename_and_path) + "/"
98
100
 
99
- # TODO: BCL will be moving over to single endpoint to manage the file upload and node creation (update eventually)
100
- file = File.open(filename_and_path, 'r')
101
+ file = File.open(filename_and_path, 'rb')
101
102
  file_b64 = Base64.encode64(file.read)
102
103
  @data = {"file" =>
103
104
  {
104
105
  "file" => "#{file_b64}",
105
106
  "filesize" => "#{File.size(filename_and_path)}",
106
107
  "filename" => filename
107
- }
108
- }
109
-
110
- res = RestClient.post "http://#{@config[:server][:url]}/api/file", @data.to_json, :content_type => :json, :cookies => @session, :accept => :json
111
-
112
- if res.code == 200
113
- fid = JSON.parse(res.body)["fid"]
114
-
115
- #post the node now with reference to this fid
116
- @data = {"node" =>
117
- {"type" => "nrel_component",
118
- "status" => 1, #NOTE THIS ONLY WORKS IF YOU ARE ADMIN
119
- "field_tar_file" =>
120
- {"und" => [
121
- {"fid" => fid}
122
- ]
123
- }
108
+ },
109
+ "node" =>
110
+ {
111
+ "type" => "#{content_type}"#,
112
+ #"status" => 1 #NOTE THIS ONLY WORKS IF YOU ARE ADMIN
124
113
  }
125
- }
126
-
127
- res = RestClient.post "http://#{@config[:server][:url]}/api/node", @data.to_json, :content_type => :json, :cookies => @session, :accept => :json
114
+ }
128
115
 
116
+ res = RestClient.post "http://#{@config[:server][:url]}/api/content", @data.to_json, :content_type => :json, :cookies => @session, :accept => :json
117
+
118
+ if res.code == 200
129
119
  res_j = JSON.parse(res.body)
130
120
 
131
121
  if res.code == 200
@@ -153,7 +143,7 @@ module BCL
153
143
  [valid, res_j]
154
144
  end
155
145
 
156
- def push_components(array_of_components, skip_files_with_receipts)
146
+ def push_contents(array_of_components, skip_files_with_receipts, content_type)
157
147
  logs = []
158
148
  array_of_components.each do |comp|
159
149
  receipt_file = File.dirname(comp) + "/" + File.basename(comp, '.tar.gz') + ".receipt"
@@ -163,23 +153,29 @@ module BCL
163
153
  else
164
154
  log_message = "pushing component #{comp}: "
165
155
  puts log_message
166
- valid, res = push_component(comp, true)
156
+ valid, res = push_content(comp, true, content_type)
167
157
  log_message += " #{valid} #{res.inspect.chomp}"
168
158
  end
169
- puts log_message
170
159
  logs << log_message
171
160
  end
172
161
 
173
162
  logs
174
163
  end
175
164
 
165
+ # Simple method to search bcl and return the result as an XML object
166
+ def search(search_str)
167
+ full_url = "http://#{@config[:server][:url]}/api/search/#{search_str}&api_version=#{@api_version}"
168
+ res = RestClient.get "#{full_url}"
169
+ xml = LibXML::XML::Document.string(res.body)
170
+
171
+ xml
172
+ end
173
+
176
174
  end
177
175
 
178
176
  # TODO make this extend the component_xml class (or create a super class around components)
179
177
 
180
- module_function
181
-
182
- def gather_components(component_dir, chunk_size = 0, delete_previous_gather = false)
178
+ def BCL.gather_components(component_dir, chunk_size = 0, delete_previous_gather = false)
183
179
  @dest_filename = "components"
184
180
  @dest_file_ext = "tar.gz"
185
181
 
@@ -178,6 +178,13 @@ end # if $have_win32ole
178
178
  filename = values.delete_at(0)
179
179
  filetype = values.delete_at(0)
180
180
  filepath = values.delete_at(0)
181
+ #not all components(rows) have all files; skip if filename "" or nil
182
+ next if filename == "" or filename == nil
183
+ #skip the file if it doesn't exist at the specified location
184
+ if not File.exists?(filepath)
185
+ puts "[ComponentSpreadsheet] ERROR #{filepath} -> File does not exist, will not be included in component xml"
186
+ next #go to the next file
187
+ end
181
188
  component_xml.add_file(software_program, version, filepath, filename, filetype)
182
189
 
183
190
  else
@@ -270,7 +277,8 @@ end # if $have_win32ole
270
277
  component.uid = xlsx_worksheet.Range("B#{i}").value
271
278
  if component.uid.nil? or component.uid.empty?
272
279
  component.uid = UUID.new.generate
273
- xlsx_worksheet.Range("B#{i}").value = component.uid
280
+ xlsx_worksheet.Range("B#{i}").value = component.uid
281
+ exit
274
282
  end
275
283
 
276
284
  # always write new version id
@@ -28,51 +28,25 @@ require 'csv'
28
28
 
29
29
  # required gems
30
30
  require 'builder' #gem install builder (creates xml files)
31
- require 'uuid' # gem install uuid
31
+
32
32
  require 'bcl/tar_ball'
33
+ require 'bcl/bcl_xml'
33
34
 
34
35
 
35
36
  module BCL
36
-
37
- SCHEMA_LOCATION = "component.xsd"
38
-
39
- ProvStruct = Struct.new(:author, :datetime, :comment)
40
- TagsStruct = Struct.new(:descriptor)
41
- AttrStruct = Struct.new(:name, :value, :datatype, :units)
42
- FileStruct = Struct.new(:version_software_program, :version_id, :fqp_file, :filename, :filetype)
43
- #cost_type is an enumeration (not enforced) of installation, material, operations and maintenance,
44
- #variable operations and maintenance, salvage
45
- CostStruct = Struct.new(:cost_name, :cost_type, :category, :value, :interval,
46
- :interval_units, :year, :location, :units, :currency, :source,
47
- :reference_component_name, :reference_component_id)
48
- ObjectStruct = Struct.new(:obj_type, :obj_instance)
49
-
50
- class Component
51
- attr_accessor :name
52
- attr_accessor :uid
53
- attr_accessor :comp_version_id
54
- attr_accessor :description
37
+ class Component < BaseXml
55
38
  attr_accessor :comment
56
39
  attr_accessor :source_manufacturer
57
40
  attr_accessor :source_model
58
41
  attr_accessor :source_serial_no
59
42
  attr_accessor :source_year
60
43
  attr_accessor :source_url
61
- attr_accessor :tags
62
- attr_accessor :provenance
63
- attr_accessor :attributes
64
- attr_accessor :files
65
- attr_accessor :costs
66
44
  attr_accessor :objects
67
45
 
68
- public
69
-
70
46
  #the save path is where the component will be saved
71
47
  def initialize(save_path)
72
- @name = "" #this is also a unique identifier to the component...
73
- @uid = UUID.new.generate
74
- @comp_version_id = UUID.new.generate
75
- @description = ""
48
+ super(save_path)
49
+
76
50
  @comment = ""
77
51
  @source_manufacturer = ""
78
52
  @source_model = ""
@@ -81,23 +55,17 @@ module BCL
81
55
  @source_url = ""
82
56
 
83
57
  #these items have multiple instances
84
- @provenance = []
85
- @tags = []
86
- @attributes = []
87
- @files = []
58
+
88
59
  @costs = []
89
60
  @objects = [] #container for saving the idf/osm snippets
90
61
 
91
62
  @path = save_path
92
63
 
93
- #puts "[ComponentXml] " + @path
94
- #need to hit a webservice to validate which tags and attributes are
95
- #available (including units?)
96
-
97
64
  #todo: validate against master taxonomy
98
65
  end
99
66
 
100
- def open_component(filename)
67
+ # TODO This isn't implemented at the moment
68
+ def open_component_xml(filename)
101
69
  read_component_xml(filename)
102
70
  end
103
71
 
@@ -152,49 +120,6 @@ module BCL
152
120
  #puts "[ComponentXml] " + Dir.pwd
153
121
  end
154
122
 
155
- def add_provenance(author, datetime, comment)
156
- prov = ProvStruct.new
157
- prov.author = author
158
- prov.datetime = datetime
159
- prov.comment = comment
160
-
161
- @provenance << prov
162
- end
163
-
164
- def add_tag(tag_name)
165
- tag = TagsStruct.new
166
- tag.descriptor = tag_name
167
-
168
- @tags << tag
169
- end
170
-
171
- def add_attribute(name, value, units, datatype = nil)
172
- attr = AttrStruct.new
173
- attr.name = name
174
- attr.value = value
175
-
176
- if !datatype.nil?
177
- attr.datatype = datatype
178
- else
179
- attr.datatype = get_datatype(value)
180
- end
181
- attr.units = units
182
-
183
- @attributes << attr
184
- end
185
-
186
- def add_file(version_sp, version_id, fqp_file, filename, filetype)
187
- fs = FileStruct.new
188
- fs.version_software_program = version_sp
189
- fs.version_id = version_id
190
- fs.fqp_file = fqp_file
191
- fs.filename = filename
192
- fs.filetype = filetype
193
-
194
- @files << fs
195
- end
196
-
197
-
198
123
  def add_cost(cost_name, cost_type, category, value, units, interval, interval_units, year, location, currency,
199
124
  source, reference_component_name, reference_component_id)
200
125
  cs = CostStruct.new
@@ -325,21 +250,26 @@ module BCL
325
250
  end
326
251
 
327
252
  def save_component_xml(dir_path = resolve_path)
253
+ FileUtils.mkpath(dir_path) if !File.exists?(dir_path)
254
+
255
+ generate_uuid() if @uuid.nil?
256
+ generate_vuid() if @vuid.nil?
257
+
328
258
  xmlfile = File.new(dir_path + '/component.xml', 'w')
329
259
  comp_xml = Builder::XmlMarkup.new(:target => xmlfile, :indent=>2)
330
260
 
331
261
  #setup the xml file
332
262
  comp_xml.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
333
263
  comp_xml.component("xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
334
- "xsi:noNamespaceSchemaLocation"=>"#{SCHEMA_LOCATION}") {
264
+ "xsi:noNamespaceSchemaLocation"=>"#{@schema_url}") {
335
265
  comp_xml.name @name
336
- comp_xml.uid @uid
337
- comp_xml.version_id @comp_version_id
266
+ comp_xml.uid @uuid
267
+ comp_xml.version_id @vuid
338
268
  comp_xml.description @description if @description != ""
339
269
  comp_xml.comment @comment if @comment != ""
340
270
 
341
271
  comp_xml.provenances {
342
- @provenance.each do |prov|
272
+ @provenances.each do |prov|
343
273
  comp_xml.provenance {
344
274
  comp_xml.author prov.author
345
275
  comp_xml.datetime prov.datetime
@@ -428,49 +358,6 @@ module BCL
428
358
 
429
359
  xmlfile.close
430
360
  end
431
-
432
- def get_attribute(attribute_name)
433
- result = nil
434
- @attributes.each do |attr|
435
- if attr.name == attribute_name
436
- result = attr
437
- end
438
- end
439
-
440
- result
441
-
442
- end
443
-
444
- #return the title case of the string
445
- def tc(input)
446
- val = input.gsub(/\b\w/){$&.upcase}
447
- if val.downcase == "energyplus"
448
- val = "EnergyPlus"
449
- end
450
- return val
451
- end
452
-
453
- private
454
-
455
- def get_datatype(input_value)
456
- dt = 'undefined'
457
-
458
- # simple method to test if the input_value is a string, float, or integer.
459
- # First convert the value back to a string for testing (in case it was passed as a float/integer)
460
- test = input_value.to_s
461
- input_value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
462
-
463
- if input_value.is_a?(Fixnum) || input_value.is_a?(Bignum)
464
- dt = "int"
465
- elsif input_value.is_a?(Float)
466
- dt = "float"
467
- else
468
- dt = "string"
469
- end
470
-
471
- dt
472
- end
473
-
474
361
  end
475
362
 
476
363
  end # module BCL