Class: BCL::Component

Inherits:
BaseXml show all
Defined in:
lib/bcl/component.rb

Instance Attribute Summary collapse

Attributes inherited from BaseXml

#attributes, #costs, #files, #provenances, #tags, #uuid, #vuid

Instance Method Summary collapse

Methods inherited from BaseXml

#add_attribute, #add_file, #add_provenance, #add_tag, #generate_uuid, #generate_vuid, #get_attribute, #get_datatype, #tc

Constructor Details

#initialize(save_path) ⇒ Component

the save path is where the component will be saved



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/bcl/component.rb', line 32

def initialize(save_path)
  super(save_path)

  @comment = ''
  @source_manufacturer = ''
  @source_model = ''
  @source_serial_no = ''
  @source_year = ''
  @source_url = ''

  # these items have multiple instances

  @costs = []
  @objects = [] # container for saving the idf/osm snippets

  @path = save_path

  # TODO: validate against master taxonomy
end

Instance Attribute Details

#commentObject

Returns the value of attribute comment.



12
13
14
# File 'lib/bcl/component.rb', line 12

def comment
  @comment
end

#comp_version_idObject

Returns the value of attribute comp_version_id.



21
22
23
# File 'lib/bcl/component.rb', line 21

def comp_version_id
  @comp_version_id
end

#descriptionObject

Returns the value of attribute description.



22
23
24
# File 'lib/bcl/component.rb', line 22

def description
  @description
end

#fidelity_levelObject

Returns the value of attribute fidelity_level.



24
25
26
# File 'lib/bcl/component.rb', line 24

def fidelity_level
  @fidelity_level
end

#modeler_descriptionObject

Returns the value of attribute modeler_description.



23
24
25
# File 'lib/bcl/component.rb', line 23

def modeler_description
  @modeler_description
end

#nameObject

Returns the value of attribute name.



19
20
21
# File 'lib/bcl/component.rb', line 19

def name
  @name
end

#objectsObject

Returns the value of attribute objects.



18
19
20
# File 'lib/bcl/component.rb', line 18

def objects
  @objects
end

#source_manufacturerObject

Returns the value of attribute source_manufacturer.



13
14
15
# File 'lib/bcl/component.rb', line 13

def source_manufacturer
  @source_manufacturer
end

#source_modelObject

Returns the value of attribute source_model.



14
15
16
# File 'lib/bcl/component.rb', line 14

def source_model
  @source_model
end

#source_serial_noObject

Returns the value of attribute source_serial_no.



15
16
17
# File 'lib/bcl/component.rb', line 15

def source_serial_no
  @source_serial_no
end

#source_urlObject

Returns the value of attribute source_url.



17
18
19
# File 'lib/bcl/component.rb', line 17

def source_url
  @source_url
end

#source_yearObject

Returns the value of attribute source_year.



16
17
18
# File 'lib/bcl/component.rb', line 16

def source_year
  @source_year
end

#uidObject

Returns the value of attribute uid.



20
21
22
# File 'lib/bcl/component.rb', line 20

def uid
  @uid
end

Instance Method Details

#add_cost(cost_name, cost_type, category, value, units, interval, interval_units, year, location, currency, source, reference_component_name, reference_component_id) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/bcl/component.rb', line 114

def add_cost(cost_name, cost_type, category, value, units, interval, interval_units, year, location, currency,
             source, reference_component_name, reference_component_id)
  cs = CostStruct.new
  cs.cost_name = cost_name
  cs.cost_type = cost_type
  cs.category = category
  cs.value = value
  cs.interval = interval
  cs.interval_units = interval_units
  cs.year = year
  cs.location = location
  cs.units = units
  cs.currency = currency
  cs.source = source
  cs.reference_component_name = reference_component_name
  cs.reference_component_id = reference_component_id

  @costs << cs
end

#add_object(object_type, object_instance) ⇒ Object



134
135
136
137
138
139
140
# File 'lib/bcl/component.rb', line 134

def add_object(object_type, object_instance)
  ob = ObjectStruct.new
  ob.obj_type = object_type
  ob.obj_instance = object_instance

  @objects << ob
end

#create_os_component(osobj) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/bcl/component.rb', line 187

def create_os_component(osobj)
  osobj.getCostLineItems.each do |os|
    @costs.each do |cost|
      # figure out costs for constructions
      os.setMaterialCost(cost.value.to_f) if cost.category == 'material'
      if cost.category == 'installation'
        os.setInstallationCost(cost.value.to_f)
        os.setExpectedLife(cost.interval.to_i)
      end
      os.setFixedOM(cost.value.to_f) if cost.category == 'operations and maintenance'
      os.setVariableOM(cost.value.to_f) if cost.category == 'variable operations and maintenance'
      os.setSalvageCost(cost.value.to_f) if cost.category == 'salvage'
    end
  end
  newcomp = osobj.createComponent

  cd = newcomp.componentData
  cd.setDescription(@description)

  at = newcomp.componentData.componentDataAttributes
  @attributes.each do |attrib|
    if (attrib.value.to_s != '') && (attrib.name.to_s != '')
      if attrib.units != ''
        at.addAttribute(tc(attrib.name), attrib.value, attrib.units)
      else
        at.addAttribute(tc(attrib.name), attrib.value)
      end
    end
  end

  tg = newcomp.componentData.componentDataTags
  comp_tag = ''
  @tags.each do |tag|
    tg.addTag(tc(tag.descriptor))
    if (tag.descriptor != 'energyplus') && (tag.descriptor != 'construction')
      # create a map of component tags to directories
      comp_tag = tag.descriptor
      if comp_tag == 'interior wall'
        comp_tag = 'interiorwalls'
      elsif comp_tag == 'exterior wall'
        comp_tag = 'exteriorwalls'
      elsif comp_tag == 'exterior slab'
        comp_tag = 'exteriorslabs'
      elsif comp_tag == 'exposed floor'
        comp_tag = 'exposedfloors'
      elsif comp_tag == 'attic floor'
        comp_tag = 'atticfloors'
      elsif comp_tag == 'roof'
        comp_tag = 'roofs'
      elsif comp_tag == 'door'
        comp_tag = 'doors'
      elsif comp_tag == 'skylight'
        comp_tag = 'skylights'
      elsif comp_tag == 'window'
        comp_tag = 'windows'
      end
      puts comp_tag
    end
  end

  newcomp
end

#open_component_xml(filename) ⇒ Object

TODO: This isn’t implemented at the moment



53
54
55
# File 'lib/bcl/component.rb', line 53

def open_component_xml(filename)
  read_component_xml(filename)
end

#osc_resolve_pathObject



164
165
166
167
168
169
# File 'lib/bcl/component.rb', line 164

def osc_resolve_path
  FileUtils.mkdir_p(@path) unless File.directory?(@path)
  new_path = "#{@path}/osc_#{name.gsub(/\W/, '_').gsub(/___/, '_').gsub(/__/, '_').chomp('_').strip}"
  FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
  result = new_path
end

#osm_resolve_pathObject



157
158
159
160
161
162
# File 'lib/bcl/component.rb', line 157

def osm_resolve_path
  FileUtils.mkdir_p(@path) unless File.directory?(@path)
  new_path = "#{@path}/osm_#{name.gsub(/\W/, '_').gsub(/___/, '_').gsub(/__/, '_').chomp('_').strip}"
  FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
  result = new_path
end

#resolve_component_path(component_type) ⇒ Object



171
172
173
174
175
176
177
178
# File 'lib/bcl/component.rb', line 171

def resolve_component_path(component_type)
  FileUtils.mkdir_p(@path) unless File.directory?(@path)
  new_path = @path + '/OpenStudio'
  FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
  new_path += "/#{component_type}"
  FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
  new_path
end

#resolve_pathObject



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/bcl/component.rb', line 142

def resolve_path
  FileUtils.mkdir_p(@path) unless File.directory?(@path)

  # TODO: should probably save all components with uid instead of name to avoid path length limitation issues
  # for now, switch to uid instead of name if larger than arbitrary number of characters
  if @name.size < 75
    new_path = "#{@path}/#{name.gsub(/\W/, '_').gsub(/___/, '_').gsub(/__/, '_').chomp('_').strip}"
  else
    new_path = "#{@path}/#{@uid}"
  end

  FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
  result = new_path
end

#save_component_xml(dir_path = resolve_path) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/bcl/component.rb', line 250

def save_component_xml(dir_path = resolve_path)
  FileUtils.mkpath(dir_path) unless File.exist?(dir_path)

  # make sure the uid and vid are pulled in from the Component
  @uuid = @uid
  @vuid = @comp_version_id

  if @uuid.nil?
    puts 'uid was missing; creating a new one'
    generate_uuid
  end

  if @vuid.nil?
    puts 'vid was missing; creating a new one'
    generate_vuid
  end

  xmlfile = File.new(dir_path + '/component.xml', 'w')
  comp_xml = Builder::XmlMarkup.new(target: xmlfile, indent: 2)

  # setup the xml file
  comp_xml.instruct! :xml, version: '1.0', encoding: 'UTF-8'
  comp_xml.component('xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
                     'xsi:noNamespaceSchemaLocation' => @schema_url.to_s) do
    comp_xml.name @name
    comp_xml.uid @uuid
    comp_xml.version_id @vuid
    comp_xml.description @description if @description != ''
    comp_xml.modeler_description @modeler_description if @modeler_description != ''
    comp_xml.comment @comment if @comment != ''

    # comp_xml.fidelity_level @fidelity_level if @fidelity_level != ""

    comp_xml.provenances do
      @provenances.each do |prov|
        comp_xml.provenance do
          comp_xml.author prov.author
          comp_xml.datetime prov.datetime
          comp_xml.comment prov.comment
        end
      end
    end

    comp_xml.tags do
      @tags.each do |tag|
        comp_xml.tag tag.descriptor
      end
    end

    comp_xml.attributes do
      @attributes.each do |attrib|
        if (attrib.value.to_s != '') && (attrib.name.to_s != '')
          comp_xml.attribute do
            comp_xml.name attrib.name
            comp_xml.value attrib.value
            comp_xml.datatype attrib.datatype
            comp_xml.units attrib.units if attrib.units != ''
          end
        end
      end
    end

    comp_xml.source do
      comp_xml.manufacturer @source_manufacturer if @source_manufacturer != ''
      comp_xml.model @source_model if @source_model != ''
      comp_xml.serial_no @source_serial_no if @source_serial_no != ''
      comp_xml.year @source_year if @source_year != ''
      comp_xml.url @source_url if @source_url != ''
    end

    unless @files.nil?
      comp_xml.files do
        @files.each do |file|
          comp_xml.file do
            comp_xml.version do
              comp_xml.software_program file.version_software_program
              comp_xml.identifier file.version_id
            end

            comp_xml.filename file.filename
            comp_xml.filetype file.filetype
          end
        end
      end
    end

    # check if we should write out costs, don't write if all values are 0 or nil
    # DLM: schema always expects costs
    write_costs = true
    # if not @costs.nil?
    #  @costs.each do |cost|
    #    if (cost.value.nil?) && (not cost.value == 0)
    #      write_costs = true
    #      break
    #    end
    #  end
    # end

    if write_costs
      comp_xml.costs do
        @costs.each do |cost|
          comp_xml.cost do
            comp_xml.instance_name cost.cost_name
            comp_xml.cost_type cost.cost_type
            comp_xml.category cost.category
            comp_xml.value cost.value
            comp_xml.units cost.units if cost.units != ''
            comp_xml.interval cost.interval if cost.interval != ''
            comp_xml.interval_units cost.interval_units if cost.interval_units != ''
            comp_xml.year cost.year if cost.year != ''
            comp_xml.currency cost.currency if cost.currency != ''
            comp_xml.source cost.source if cost.source != ''
            comp_xml.reference_component_name cost.reference_component_name if cost.reference_component_name != ''
            comp_xml.reference_component_id cost.reference_component_id if cost.reference_component_id != ''
          end
        end
      end
    end
  end

  xmlfile.close
end

#save_tar_gz(delete_files = true) ⇒ Object

savefile, save the component xml along with the files that have been added to the object



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
# File 'lib/bcl/component.rb', line 59

def save_tar_gz(delete_files = true)
  current_d = Dir.pwd
  paths = []

  save_component_xml

  paths << './component.xml'

  # copy over the files to the directory
  @files.each do |file|
    src_path = Pathname.new(file.fqp_file)
    dest_path = Pathname.new("#{resolve_path}/#{file.filename}")
    if File.exist?(src_path)
      if src_path == dest_path
        # do nothing, file is already where it needs to be
      else
        # move the file where it needs to go
        FileUtils.cp(src_path, dest_path)
      end
    else
      puts "#{src_path} -> File does not exist"
    end
    paths << "./#{file.filename}"
  end

  # take all the files and tar.gz them -- name the file the same as
  # the directory

  Dir.chdir(resolve_path.to_s)
  destination = @name.gsub(/\W/, '_').gsub(/___/, '_').gsub(/__/, '_').chomp('_').strip.to_s
  # truncate filenames for paths that are longer than 256 characters (with .tar.gz appended)
  unless (@path + destination + destination).size < 249
    destination = @uid.to_s
    puts 'truncating filename...using uid instead of name'
  end
  destination += '.tar.gz'

  File.delete(destination) if File.exist?(destination)

  BCL.tarball(destination, paths)

  Dir.chdir(current_d)

  if delete_files
    @files.each do |file|
      if File.exist?(File.dirname(file.fqp_file))
        puts "[ComponentXml] Deleting: #{File.dirname(file.fqp_file)}"
        FileUtils.rm_rf(File.dirname(file.fqp_file))
      end
    end
  end

  # puts "[ComponentXml] " + Dir.pwd
end

#tmp_resolve_pathObject



180
181
182
183
184
185
# File 'lib/bcl/component.rb', line 180

def tmp_resolve_path
  FileUtils.mkdir_p(@path) unless File.directory?(@path)
  new_path = "#{@path}/tmp_#{name.gsub(/\W/, '_').gsub(/___/, '_').gsub(/__/, '_').chomp('_').strip}"
  FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
  result = new_path
end