bcl 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bcl/{bcl_xml.rb → base_xml.rb} +132 -130
- data/lib/bcl/{component_xml.rb → component.rb} +19 -3
- data/lib/bcl/component_from_spreadsheet.rb +243 -0
- data/lib/bcl/component_methods.rb +139 -100
- data/lib/bcl/core_ext.rb +15 -0
- data/lib/bcl/master_taxonomy.rb +4 -1
- data/lib/bcl/tar_ball.rb +10 -12
- data/lib/bcl/version.rb +22 -22
- data/lib/bcl.rb +14 -3
- metadata +20 -5
- data/lib/bcl/measure_xml.rb +0 -37
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d84cc1c93cc41cbcd5e66681619123bf8a173a98
|
|
4
|
+
data.tar.gz: 99519415353a6c8dcafe3e2b558b0f0ceba001e8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c78265464c68b61f6f01cbb8f312884b219e1d95f4b049ad73b2b65b8a1d5b33d3acb1bd1c92e78e5dce8549bb112d9cd0be7c24964b299a1bfd73306861183
|
|
7
|
+
data.tar.gz: b82a8f5e0cf75223377f414ae3fec6682c8cffba04cb1904fcd655377b0a0508da278bbc98701e1e08e1e4e862e1a35076c80a07feb3305cf0641eebff34c565
|
|
@@ -1,130 +1,132 @@
|
|
|
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 :
|
|
18
|
-
attr_accessor :
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
attr_accessor :
|
|
22
|
-
attr_accessor :
|
|
23
|
-
attr_accessor :
|
|
24
|
-
attr_accessor :
|
|
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
|
-
prov
|
|
50
|
-
prov.
|
|
51
|
-
prov.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
tag
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
attr
|
|
66
|
-
attr.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
fs
|
|
81
|
-
fs.
|
|
82
|
-
fs.
|
|
83
|
-
fs.
|
|
84
|
-
fs.
|
|
85
|
-
fs.
|
|
86
|
-
fs.
|
|
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
|
-
test
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
dt = "
|
|
123
|
-
|
|
124
|
-
dt = "
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
end
|
|
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 :modeler_description
|
|
18
|
+
attr_accessor :uuid
|
|
19
|
+
attr_accessor :vuid
|
|
20
|
+
|
|
21
|
+
attr_accessor :attributes
|
|
22
|
+
attr_accessor :files
|
|
23
|
+
attr_accessor :costs
|
|
24
|
+
attr_accessor :tags
|
|
25
|
+
attr_accessor :provenances
|
|
26
|
+
|
|
27
|
+
def initialize(save_path)
|
|
28
|
+
@name = "" #this is also a unique identifier to the component...
|
|
29
|
+
@description = ""
|
|
30
|
+
@modeler_description = ""
|
|
31
|
+
|
|
32
|
+
@provenances = []
|
|
33
|
+
@tags = []
|
|
34
|
+
@attributes = []
|
|
35
|
+
@files = []
|
|
36
|
+
|
|
37
|
+
@schema_url = "schema.xsd"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def generate_uuid()
|
|
41
|
+
@uuid = UUID.new.generate
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def generate_vuid()
|
|
45
|
+
@vuid = UUID.new.generate
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def add_provenance(author, datetime, comment)
|
|
49
|
+
prov = ProvStruct.new
|
|
50
|
+
prov.author = author
|
|
51
|
+
prov.datetime = datetime
|
|
52
|
+
prov.comment = comment
|
|
53
|
+
|
|
54
|
+
@provenances << prov
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def add_tag(tag_name)
|
|
58
|
+
tag = TagsStruct.new
|
|
59
|
+
tag.descriptor = tag_name
|
|
60
|
+
|
|
61
|
+
@tags << tag
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def add_attribute(name, value, units, datatype = nil)
|
|
65
|
+
attr = AttrStruct.new
|
|
66
|
+
attr.name = name
|
|
67
|
+
attr.value = value
|
|
68
|
+
|
|
69
|
+
if !datatype.nil?
|
|
70
|
+
attr.datatype = datatype
|
|
71
|
+
else
|
|
72
|
+
attr.datatype = get_datatype(value)
|
|
73
|
+
end
|
|
74
|
+
attr.units = units
|
|
75
|
+
|
|
76
|
+
@attributes << attr
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def add_file(version_sp, version_id, fqp_file, filename, filetype, usage_type = nil, checksum = nil)
|
|
80
|
+
fs = FileStruct.new
|
|
81
|
+
fs.version_software_program = version_sp
|
|
82
|
+
fs.version_id = version_id
|
|
83
|
+
fs.fqp_file = fqp_file
|
|
84
|
+
fs.filename = filename
|
|
85
|
+
fs.filetype = filetype
|
|
86
|
+
fs.usage_type = usage_type if usage_type != nil
|
|
87
|
+
fs.checksum = checksum if checksum != nil
|
|
88
|
+
|
|
89
|
+
@files << fs
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
#return the title case of the string
|
|
93
|
+
def tc(input)
|
|
94
|
+
val = input.gsub(/\b\w/) { $&.upcase }
|
|
95
|
+
if val.downcase == "energyplus"
|
|
96
|
+
val = "EnergyPlus"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
val
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def get_attribute(attribute_name)
|
|
103
|
+
result = nil
|
|
104
|
+
@attributes.each do |attr|
|
|
105
|
+
if attr.name == attribute_name
|
|
106
|
+
result = attr
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
result
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def get_datatype(input_value)
|
|
114
|
+
dt = 'undefined'
|
|
115
|
+
|
|
116
|
+
# simple method to test if the input_value is a string, float, or integer.
|
|
117
|
+
# First convert the value back to a string for testing (in case it was passed as a float/integer)
|
|
118
|
+
test = input_value.to_s
|
|
119
|
+
input_value = test.match('\.').nil? ? Integer(test) : Float(test) rescue test.to_s
|
|
120
|
+
|
|
121
|
+
if input_value.is_a?(Fixnum) || input_value.is_a?(Bignum)
|
|
122
|
+
dt = "int"
|
|
123
|
+
elsif input_value.is_a?(Float)
|
|
124
|
+
dt = "float"
|
|
125
|
+
else
|
|
126
|
+
dt = "string"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
dt
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -34,6 +34,7 @@ module BCL
|
|
|
34
34
|
attr_accessor :uid
|
|
35
35
|
attr_accessor :comp_version_id
|
|
36
36
|
attr_accessor :description
|
|
37
|
+
attr_accessor :modeler_description
|
|
37
38
|
attr_accessor :fidelity_level
|
|
38
39
|
attr_accessor :source_manufacturer
|
|
39
40
|
attr_accessor :source_model
|
|
@@ -98,7 +99,13 @@ module BCL
|
|
|
98
99
|
#the directory
|
|
99
100
|
|
|
100
101
|
Dir.chdir("#{resolve_path}")
|
|
101
|
-
destination = "#{@name.gsub(/\W/,'_').gsub(/___/,'_').gsub(/__/,'_').chomp('_').strip}
|
|
102
|
+
destination = "#{@name.gsub(/\W/,'_').gsub(/___/,'_').gsub(/__/,'_').chomp('_').strip}"
|
|
103
|
+
# truncate filenames for paths that are longer than 256 characters (with .tar.gz appended)
|
|
104
|
+
unless (@path + destination + destination).size < 249
|
|
105
|
+
destination = "#{@uid}"
|
|
106
|
+
puts "truncating filename...using uid instead of name"
|
|
107
|
+
end
|
|
108
|
+
destination = destination + ".tar.gz"
|
|
102
109
|
|
|
103
110
|
File.delete(destination) if File.exists?(destination)
|
|
104
111
|
|
|
@@ -148,7 +155,15 @@ module BCL
|
|
|
148
155
|
|
|
149
156
|
def resolve_path
|
|
150
157
|
FileUtils.mkdir_p(@path) unless File.directory?(@path)
|
|
151
|
-
|
|
158
|
+
|
|
159
|
+
# TODO: should probably save all components with uid instead of name to avoid path length limitation issues
|
|
160
|
+
# for now, switch to uid instead of name if larger than arbitrary number of characters
|
|
161
|
+
if @name.size < 75
|
|
162
|
+
new_path = "#{@path}/#{name.gsub(/\W/,'_').gsub(/___/,'_').gsub(/__/,'_').chomp('_').strip}"
|
|
163
|
+
else
|
|
164
|
+
new_path = "#{@path}/#{@uid}"
|
|
165
|
+
end
|
|
166
|
+
|
|
152
167
|
FileUtils.mkdir_p(new_path) unless File.directory?(new_path)
|
|
153
168
|
result = new_path
|
|
154
169
|
end
|
|
@@ -275,9 +290,10 @@ module BCL
|
|
|
275
290
|
comp_xml.uid @uuid
|
|
276
291
|
comp_xml.version_id @vuid
|
|
277
292
|
comp_xml.description @description if @description != ""
|
|
293
|
+
comp_xml.modeler_description @modeler_description if @modeler_description != ""
|
|
278
294
|
comp_xml.comment @comment if @comment != ""
|
|
279
295
|
|
|
280
|
-
comp_xml.fidelity_level @fidelity_level if @fidelity_level != ""
|
|
296
|
+
#comp_xml.fidelity_level @fidelity_level if @fidelity_level != ""
|
|
281
297
|
|
|
282
298
|
comp_xml.provenances {
|
|
283
299
|
@provenances.each do |prov|
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
######################################################################
|
|
2
|
+
# Copyright (c) 2008-2013, Alliance for Sustainable Energy.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18
|
+
######################################################################
|
|
19
|
+
|
|
20
|
+
# Converts a custom Excel spreadsheet format to BCL components for upload
|
|
21
|
+
|
|
22
|
+
require 'rubyXL'
|
|
23
|
+
require 'bcl'
|
|
24
|
+
|
|
25
|
+
module BCL
|
|
26
|
+
|
|
27
|
+
WorksheetStruct = Struct.new(:name, :components)
|
|
28
|
+
HeaderStruct = Struct.new(:name, :children)
|
|
29
|
+
ComponentStruct = Struct.new(:row, :name, :uid, :version_id, :headers, :values)
|
|
30
|
+
|
|
31
|
+
class ComponentFromSpreadsheet
|
|
32
|
+
|
|
33
|
+
@@changed = false
|
|
34
|
+
|
|
35
|
+
public
|
|
36
|
+
|
|
37
|
+
#initialize with Excel spreadsheet to read
|
|
38
|
+
def initialize(xlsx_path, worksheet_names =["all"])
|
|
39
|
+
|
|
40
|
+
@xlsx_path = Pathname.new(xlsx_path).realpath.to_s
|
|
41
|
+
@worksheets = []
|
|
42
|
+
|
|
43
|
+
begin
|
|
44
|
+
xlsx= RubyXL::Parser.parse(@xlsx_path)
|
|
45
|
+
|
|
46
|
+
#by default, operate on all worksheets
|
|
47
|
+
if worksheet_names == ["all"]
|
|
48
|
+
xlsx.worksheets.each do |xlsx_worksheet|
|
|
49
|
+
parse_xlsx_worksheet(xlsx_worksheet)
|
|
50
|
+
end
|
|
51
|
+
else #if specific worksheets are specified, operate on them
|
|
52
|
+
worksheet_names.each do |worksheet_name|
|
|
53
|
+
parse_xlsx_worksheet(xlsx[worksheet_name])
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
#save spreadsheet if changes have been made
|
|
58
|
+
if @@changed
|
|
59
|
+
xlsx.write(@xlsx_path)
|
|
60
|
+
puts "[ComponentFromSpreadsheet] Spreadsheet changes saved"
|
|
61
|
+
end
|
|
62
|
+
ensure
|
|
63
|
+
xlsx=nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def save(save_path, chunk_size = 1000, delete_old_gather = false)
|
|
68
|
+
#FileUtils.rm_rf(save_path) if File.exists?(save_path) and File.directory?(save_path)
|
|
69
|
+
# TODO: validate against taxonomy
|
|
70
|
+
|
|
71
|
+
@worksheets.each do |worksheet|
|
|
72
|
+
worksheet.components.each do |component|
|
|
73
|
+
component_xml = Component.new("#{save_path}/components")
|
|
74
|
+
component_xml.name = component.name
|
|
75
|
+
component_xml.uid = component.uid
|
|
76
|
+
|
|
77
|
+
# this tag is how we know where this goes in the taxonomy
|
|
78
|
+
component_xml.add_tag(worksheet.name)
|
|
79
|
+
puts "tag: #{worksheet.name}"
|
|
80
|
+
|
|
81
|
+
values = component.values
|
|
82
|
+
|
|
83
|
+
component.headers.each do |header|
|
|
84
|
+
if /description/i.match(header.name)
|
|
85
|
+
name = values.delete_at(0) # name, uid already processed
|
|
86
|
+
uid = values.delete_at(0)
|
|
87
|
+
description = values.delete_at(0)
|
|
88
|
+
component_xml.modeler_description = values.delete_at(0)
|
|
89
|
+
component_xml.description = description
|
|
90
|
+
elsif /provenance/i.match(header.name)
|
|
91
|
+
author = values.delete_at(0)
|
|
92
|
+
datetime = values.delete_at(0)
|
|
93
|
+
if datetime.nil?
|
|
94
|
+
#puts "[ComponentSpreadsheet] WARNING missing the date in the datetime column in the spreadsheet - assuming today"
|
|
95
|
+
datetime = DateTime.new
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
comment = values.delete_at(0)
|
|
99
|
+
component_xml.add_provenance(author.to_s, datetime.strftime("%Y-%m-%d"), comment.to_s)
|
|
100
|
+
elsif /tag/i.match(header.name)
|
|
101
|
+
value = values.delete_at(0)
|
|
102
|
+
component_xml.add_tag(value)
|
|
103
|
+
elsif /attribute/i.match(header.name)
|
|
104
|
+
value = values.delete_at(0)
|
|
105
|
+
name = header.children[0]
|
|
106
|
+
units = ""
|
|
107
|
+
if match_data = /(.*)\((.*)\)/.match(name)
|
|
108
|
+
name = match_data[1].strip
|
|
109
|
+
units = match_data[2].strip
|
|
110
|
+
end
|
|
111
|
+
component_xml.add_attribute(name, value, units)
|
|
112
|
+
elsif /source/i.match(header.name)
|
|
113
|
+
manufacturer = values.delete_at(0)
|
|
114
|
+
model = values.delete_at(0)
|
|
115
|
+
serial_no = values.delete_at(0)
|
|
116
|
+
year = values.delete_at(0)
|
|
117
|
+
url = values.delete_at(0)
|
|
118
|
+
component_xml.source_manufacturer = manufacturer
|
|
119
|
+
component_xml.source_model = model
|
|
120
|
+
component_xml.source_serial_no = serial_no
|
|
121
|
+
component_xml.source_year = year
|
|
122
|
+
component_xml.source_url = url
|
|
123
|
+
elsif /file/i.match(header.name)
|
|
124
|
+
software_program = values.delete_at(0)
|
|
125
|
+
version = values.delete_at(0)
|
|
126
|
+
filename = values.delete_at(0)
|
|
127
|
+
filetype = values.delete_at(0)
|
|
128
|
+
filepath = values.delete_at(0)
|
|
129
|
+
#not all components(rows) have all files; skip if filename "" or nil
|
|
130
|
+
next if filename == "" or filename == nil
|
|
131
|
+
#skip the file if it doesn't exist at the specified location
|
|
132
|
+
if not File.exists?(filepath)
|
|
133
|
+
puts "[ComponentFromSpreadsheet] ERROR #{filepath} -> File does not exist, will not be included in component xml"
|
|
134
|
+
next #go to the next file
|
|
135
|
+
end
|
|
136
|
+
component_xml.add_file(software_program, version, filepath, filename, filetype)
|
|
137
|
+
else
|
|
138
|
+
fail "Unknown section #{header.name}"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
component_xml.save_tar_gz(false)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
BCL.gather_components(save_path, chunk_size, delete_old_gather)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
private
|
|
150
|
+
|
|
151
|
+
def parse_xlsx_worksheet(xlsx_worksheet)
|
|
152
|
+
worksheet = WorksheetStruct.new
|
|
153
|
+
worksheet.name = xlsx_worksheet[0][0].value #get A1, order is: row, col
|
|
154
|
+
worksheet.components = []
|
|
155
|
+
puts "[ComponentFromSpreadsheet] Starting parsing components of type #{worksheet.name}"
|
|
156
|
+
|
|
157
|
+
# find number of rows, first column should be name, should not be empty
|
|
158
|
+
|
|
159
|
+
xlsx_data = xlsx_worksheet.extract_data
|
|
160
|
+
#puts "Data: #{xlsx_data.inspect}"
|
|
161
|
+
|
|
162
|
+
num_rows = xlsx_data.size
|
|
163
|
+
#puts "Number of Rows: #{xlsx_data.size}"
|
|
164
|
+
num_rows = 2
|
|
165
|
+
while true do
|
|
166
|
+
test = xlsx_data[num_rows][0]
|
|
167
|
+
if test.nil? or test.empty?
|
|
168
|
+
#num_rows -= 1
|
|
169
|
+
break
|
|
170
|
+
end
|
|
171
|
+
num_rows += 1
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# scan number of columns
|
|
175
|
+
headers = []
|
|
176
|
+
header = nil
|
|
177
|
+
max_col = nil
|
|
178
|
+
|
|
179
|
+
xlsx_data[0].each_with_index do |col, index|
|
|
180
|
+
value1 = xlsx_data[0][index]
|
|
181
|
+
value2 = xlsx_data[1][index]
|
|
182
|
+
|
|
183
|
+
if not value1.nil? and not value1.empty?
|
|
184
|
+
if not header.nil?
|
|
185
|
+
headers << header
|
|
186
|
+
end
|
|
187
|
+
header = HeaderStruct.new
|
|
188
|
+
header.name = value1
|
|
189
|
+
header.children = []
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
if not value2.nil? and not value2.empty?
|
|
193
|
+
if not header.nil?
|
|
194
|
+
header.children << value2
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
if (value1.nil? or value1.empty?) and (value2.nil? or value2.empty?)
|
|
199
|
+
break
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
max_col = index
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
if not header.nil?
|
|
206
|
+
headers << header
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
if not headers.empty?
|
|
210
|
+
headers[0].name = "description"
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
puts " Found #{num_rows - 2} components"
|
|
214
|
+
|
|
215
|
+
components = []
|
|
216
|
+
for i in 2..num_rows-1 do
|
|
217
|
+
component = ComponentStruct.new
|
|
218
|
+
component.row = i
|
|
219
|
+
|
|
220
|
+
# get name
|
|
221
|
+
component.name = xlsx_data[i][0]
|
|
222
|
+
|
|
223
|
+
# get uid, if empty set it
|
|
224
|
+
component.uid = xlsx_data[i][1]
|
|
225
|
+
if component.uid.nil? or component.uid.empty?
|
|
226
|
+
component.uid = UUID.new.generate
|
|
227
|
+
puts "#{component.name} uid missing; creating new one"
|
|
228
|
+
xlsx_worksheet.add_cell(i, 1, component.uid)
|
|
229
|
+
@@changed = true
|
|
230
|
+
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
component.headers = headers
|
|
234
|
+
component.values = xlsx_data[i][0..max_col]
|
|
235
|
+
worksheet.components << component
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
@worksheets << worksheet
|
|
239
|
+
|
|
240
|
+
puts "[ComponentFromSpreadsheet] Finished parsing components of type #{worksheet.name}"
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
@@ -17,8 +17,6 @@
|
|
|
17
17
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18
18
|
######################################################################
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
# required gems
|
|
22
20
|
require 'net/https'
|
|
23
21
|
|
|
24
22
|
module BCL
|
|
@@ -42,7 +40,6 @@ module BCL
|
|
|
42
40
|
load_config
|
|
43
41
|
end
|
|
44
42
|
|
|
45
|
-
|
|
46
43
|
def login(username=nil, password=nil, url=nil, group_id = nil)
|
|
47
44
|
#figure out what url to use
|
|
48
45
|
if url.nil?
|
|
@@ -65,11 +62,12 @@ module BCL
|
|
|
65
62
|
@group_id = group_id || @config[:server][:user][:group]
|
|
66
63
|
puts "logging in using credentials in .bcl/config.yml: Connecting to #{url} on port #{port} as #{username}"
|
|
67
64
|
else
|
|
68
|
-
|
|
65
|
+
@group_id = group_id
|
|
66
|
+
puts "logging in using credentials in function arguments: Connecting to #{url} on port #{port} as #{username} with group #{@group_id}"
|
|
69
67
|
end
|
|
70
68
|
|
|
71
69
|
if @group_id.nil?
|
|
72
|
-
puts "[WARNING] You did not set a group ID in your config.yml file. You can retrieve your group ID from the node number of your group page (e.g., https://bcl.nrel.gov/node/32). Will continue, but you will not be able to upload content."
|
|
70
|
+
puts "[WARNING] You did not set a group ID in your config.yml file or pass in a group ID. You can retrieve your group ID from the node number of your group page (e.g., https://bcl.nrel.gov/node/32). Will continue, but you will not be able to upload content."
|
|
73
71
|
end
|
|
74
72
|
|
|
75
73
|
@http = Net::HTTP.new(url, port)
|
|
@@ -150,32 +148,115 @@ module BCL
|
|
|
150
148
|
end
|
|
151
149
|
end
|
|
152
150
|
|
|
153
|
-
#retrieve, parse, and save metadata for BCL measures
|
|
151
|
+
# retrieve, parse, and save metadata for BCL measures
|
|
154
152
|
def measure_metadata(search_term = nil, filter_term=nil, return_all_pages = false)
|
|
155
|
-
|
|
156
|
-
#setup results directory
|
|
153
|
+
# setup results directory
|
|
157
154
|
if !File.exists?(@parsed_measures_path)
|
|
158
155
|
FileUtils.mkdir_p(@parsed_measures_path)
|
|
159
156
|
end
|
|
160
157
|
puts "...storing parsed metadata in #{@parsed_measures_path}"
|
|
161
158
|
|
|
162
|
-
#retrieve measures
|
|
163
|
-
puts "retrieving measures that match search_term: #{search_term.nil? ? "nil" :search_term} and filters: #{filter_term.nil? ? "nil" :filter_term}"
|
|
159
|
+
# retrieve measures
|
|
160
|
+
puts "retrieving measures that match search_term: #{search_term.nil? ? "nil" : search_term} and filters: #{filter_term.nil? ? "nil" : filter_term}"
|
|
164
161
|
retrieve_measures(search_term, filter_term, return_all_pages) do |measure|
|
|
165
|
-
#parse and save
|
|
162
|
+
# parse and save
|
|
166
163
|
parse_measure_metadata(measure)
|
|
167
164
|
end
|
|
168
165
|
|
|
169
|
-
|
|
166
|
+
true
|
|
170
167
|
end
|
|
171
168
|
|
|
169
|
+
# Read in an exisitng measure.rb file and extract the arguments. Note that the measure_name (display name)
|
|
170
|
+
# does not exist in the .rb file, so you have to pass this in.
|
|
171
|
+
def parse_measure_file(measure_name, measure_filename)
|
|
172
|
+
measure_hash = {}
|
|
173
|
+
if File.exists? measure_filename
|
|
174
|
+
# read in the measure file and extract some information
|
|
175
|
+
measure_string = File.read(measure_filename)
|
|
176
|
+
|
|
177
|
+
measure_hash[:classname] = measure_string.match(/class (.*) </)[1]
|
|
178
|
+
measure_hash[:path] = "#{@parsed_measures_path}/#{measure_hash[:classname]}"
|
|
179
|
+
#measure_hash[:display_name] = clean(measure_name)
|
|
180
|
+
measure_hash[:name] = measure_hash[:classname].to_underscore
|
|
181
|
+
measure_hash[:display_name] = clean(measure_hash[:name].titleize)
|
|
182
|
+
if measure_string =~ /OpenStudio::Ruleset::WorkspaceUserScript/
|
|
183
|
+
measure_hash[:measure_type] = "EnergyPlusMeasure"
|
|
184
|
+
elsif measure_string =~ /OpenStudio::Ruleset::ModelUserScript/
|
|
185
|
+
measure_hash[:measure_type] = "RubyMeasure"
|
|
186
|
+
elsif measure_string =~ /OpenStudio::Ruleset::ReportingUserScript/
|
|
187
|
+
measure_hash[:measure_type] = "ReportingMeasure"
|
|
188
|
+
else
|
|
189
|
+
raise "measure type is unknown with an inherited class in #{measure_filename}: #{measure_hash.inspect}"
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
measure_hash[:arguments] = []
|
|
193
|
+
|
|
194
|
+
args = measure_string.scan(/(.*).*=.*OpenStudio::Ruleset::OSArgument.*make(.*)Argument\((.*).*\)/)
|
|
195
|
+
args.each do |arg|
|
|
196
|
+
new_arg = {}
|
|
197
|
+
new_arg[:local_variable] = arg[0].strip
|
|
198
|
+
new_arg[:variable_type] = arg[1]
|
|
199
|
+
arg_params = arg[2].split(",")
|
|
200
|
+
new_arg[:name] = arg_params[0].gsub(/"|'/, "")
|
|
201
|
+
next if new_arg[:name] == 'info_widget'
|
|
202
|
+
choice_vector = arg_params[1] ? arg_params[1].strip : nil
|
|
203
|
+
|
|
204
|
+
# local variable name to get other attributes
|
|
205
|
+
new_arg[:display_name] = measure_string.match(/#{new_arg[:local_variable]}.setDisplayName\((.*)\)/)[1]
|
|
206
|
+
new_arg[:display_name].gsub!(/"|'/, "") if new_arg[:display_name]
|
|
207
|
+
new_arg[:display_name] = clean(new_arg[:display_name])
|
|
208
|
+
|
|
209
|
+
if measure_string =~ /#{new_arg[:local_variable]}.setDefaultValue/
|
|
210
|
+
new_arg[:default_value] = measure_string.match(/#{new_arg[:local_variable]}.setDefaultValue\((.*)\)/)[1]
|
|
211
|
+
else
|
|
212
|
+
puts "[WARNING] #{measure_hash[:name]}:#{new_arg[:name]} has no default value... will try to continue"
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
case new_arg[:variable_type]
|
|
216
|
+
when "Choice"
|
|
217
|
+
# Choices to appear to only be strings?
|
|
218
|
+
puts "Choice vector appears to be #{choice_vector}"
|
|
219
|
+
new_arg[:default_value].gsub!(/"|'/, "") if new_arg[:default_value]
|
|
172
220
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
221
|
+
# parse the choices from the measure
|
|
222
|
+
possible_choices = measure_string.scan(/#{choice_vector}.*<<.*("|')(.*)("|')/)
|
|
223
|
+
puts "Possible choices are #{possible_choices}"
|
|
224
|
+
|
|
225
|
+
if possible_choices.empty?
|
|
226
|
+
new_arg[:choices] = []
|
|
227
|
+
else
|
|
228
|
+
new_arg[:choices] = possible_choices.map { |c| c[1] }
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# if the choices are inherited from the model, then need to just display the default value which
|
|
232
|
+
# somehow magically works because that is the display name
|
|
233
|
+
if new_arg[:default_value]
|
|
234
|
+
new_arg[:choices] << new_arg[:default_value] unless new_arg[:choices].include?(new_arg[:default_value])
|
|
235
|
+
end
|
|
236
|
+
when "String"
|
|
237
|
+
new_arg[:default_value].gsub!(/"|'/, "") if new_arg[:default_value]
|
|
238
|
+
when "Bool"
|
|
239
|
+
new_arg[:default_value] = new_arg[:default_value].downcase == "true" ? true : false
|
|
240
|
+
when "Integer"
|
|
241
|
+
new_arg[:default_value] = new_arg[:default_value].to_i if new_arg[:default_value]
|
|
242
|
+
when "Double"
|
|
243
|
+
new_arg[:default_value] = new_arg[:default_value].to_f if new_arg[:default_value]
|
|
244
|
+
else
|
|
245
|
+
raise "unknown variable type of #{new_arg[:variable_type]}"
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
measure_hash[:arguments] << new_arg
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
measure_hash
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# Read the measure's information to pull out the metadata and to move into a more friendly directory name.
|
|
256
|
+
# option measure is a JSON
|
|
176
257
|
def parse_measure_metadata(measure)
|
|
177
258
|
|
|
178
|
-
#check for valid measure
|
|
259
|
+
# check for valid measure
|
|
179
260
|
if measure[:measure][:name] && measure[:measure][:uuid]
|
|
180
261
|
|
|
181
262
|
file_data = download_component(measure[:measure][:uuid])
|
|
@@ -184,14 +265,14 @@ module BCL
|
|
|
184
265
|
save_file = File.expand_path("#{@parsed_measures_path}/#{measure[:measure][:name].downcase.gsub(" ", "_")}.zip")
|
|
185
266
|
File.open(save_file, 'wb') { |f| f << file_data }
|
|
186
267
|
|
|
187
|
-
#unzip file and delete zip.
|
|
188
|
-
#TODO check that something was downloaded here before extracting zip
|
|
189
|
-
if File.
|
|
268
|
+
# unzip file and delete zip.
|
|
269
|
+
# TODO check that something was downloaded here before extracting zip
|
|
270
|
+
if File.exist? save_file
|
|
190
271
|
BCL.extract_zip(save_file, @parsed_measures_path, true)
|
|
191
272
|
|
|
192
273
|
# catch a weird case where there is an extra space in an unzip file structure but not in the measure.name
|
|
193
274
|
if measure[:measure][:name] == "Add Daylight Sensor at Center of Spaces with a Specified Space Type Assigned"
|
|
194
|
-
|
|
275
|
+
unless File.exists? "#{@parsed_measures_path}/#{measure[:measure][:name]}"
|
|
195
276
|
temp_dir_name = "#{@parsed_measures_path}/Add Daylight Sensor at Center of Spaces with a Specified Space Type Assigned"
|
|
196
277
|
FileUtils.move(temp_dir_name, "#{@parsed_measures_path}/#{measure[:measure][:name]}")
|
|
197
278
|
end
|
|
@@ -202,92 +283,15 @@ module BCL
|
|
|
202
283
|
# Read the measure.rb file
|
|
203
284
|
#puts "save dir name #{temp_dir_name}"
|
|
204
285
|
measure_filename = "#{temp_dir_name}/measure.rb"
|
|
205
|
-
|
|
206
|
-
measure_hash = {}
|
|
207
|
-
# read in the measure file and extract some information
|
|
208
|
-
measure_string = File.read(measure_filename)
|
|
209
|
-
|
|
210
|
-
measure_hash[:classname] = measure_string.match(/class (.*) </)[1]
|
|
211
|
-
measure_hash[:path] = "#{@parsed_measures_path}/#{measure_hash[:classname]}"
|
|
212
|
-
measure_hash[:name] = measure[:measure][:name]
|
|
213
|
-
if measure_string =~ /OpenStudio::Ruleset::WorkspaceUserScript/
|
|
214
|
-
measure_hash[:measure_type] = "EnergyPlusMeasure"
|
|
215
|
-
elsif measure_string =~ /OpenStudio::Ruleset::ModelUserScript/
|
|
216
|
-
measure_hash[:measure_type] = "RubyMeasure"
|
|
217
|
-
elsif measure_string =~ /OpenStudio::Ruleset::ReportingUserScript/
|
|
218
|
-
measure_hash[:measure_type] = "ReportingMeasure"
|
|
219
|
-
else
|
|
220
|
-
raise "measure type is unknown with an inherited class in #{measure_filename}: #{measure_hash.inspect}"
|
|
221
|
-
end
|
|
286
|
+
measure_hash = parse_measure_file(measure[:measure][:name], measure_filename)
|
|
222
287
|
|
|
288
|
+
unless measure_hash.empty?
|
|
223
289
|
# move the directory to the class name
|
|
224
290
|
FileUtils.rm_rf(measure_hash[:path]) if File.exists?(measure_hash[:path]) && temp_dir_name != measure_hash[:path]
|
|
225
291
|
FileUtils.move(temp_dir_name, measure_hash[:path]) unless temp_dir_name == measure_hash[:path]
|
|
226
292
|
|
|
227
|
-
measure_hash[:arguments] = []
|
|
228
|
-
|
|
229
|
-
args = measure_string.scan(/(.*).*=.*OpenStudio::Ruleset::OSArgument::make(.*)Argument\((.*).*\)/)
|
|
230
|
-
#puts "found #{args.size} arguments for measure '#{measure[:measure][:name]}'"
|
|
231
|
-
args.each do |arg|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
new_arg = {}
|
|
235
|
-
new_arg[:local_variable] = arg[0].strip
|
|
236
|
-
new_arg[:variable_type] = arg[1]
|
|
237
|
-
arg_params = arg[2].split(",")
|
|
238
|
-
new_arg[:name] = arg_params[0].gsub(/"|'/, "")
|
|
239
|
-
next if new_arg[:name] == 'info_widget'
|
|
240
|
-
choice_vector = arg_params[1] ? arg_params[1].strip : nil
|
|
241
|
-
|
|
242
|
-
# local variable name to get other attributes
|
|
243
|
-
new_arg[:display_name] = measure_string.match(/#{new_arg[:local_variable]}.setDisplayName\((.*)\)/)[1]
|
|
244
|
-
new_arg[:display_name].gsub!(/"|'/, "") if new_arg[:display_name]
|
|
245
|
-
|
|
246
|
-
if measure_string =~ /#{new_arg[:local_variable]}.setDefaultValue/
|
|
247
|
-
new_arg[:default_value] = measure_string.match(/#{new_arg[:local_variable]}.setDefaultValue\((.*)\)/)[1]
|
|
248
|
-
else
|
|
249
|
-
puts "[WARNING] #{measure_hash[:name]}:#{new_arg[:name]} has no default value... will try to continue"
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
case new_arg[:variable_type]
|
|
253
|
-
when "Choice"
|
|
254
|
-
# Choices to appear to only be strings?
|
|
255
|
-
puts "Choice vector appears to be #{choice_vector}"
|
|
256
|
-
new_arg[:default_value].gsub!(/"|'/, "") if new_arg[:default_value]
|
|
257
|
-
|
|
258
|
-
# parse the choices from the measure
|
|
259
|
-
possible_choices = measure_string.scan(/#{choice_vector}.*<<.*("|')(.*)("|')/)
|
|
260
|
-
puts "Possible choices are #{possible_choices}"
|
|
261
|
-
|
|
262
|
-
if possible_choices.empty?
|
|
263
|
-
new_arg[:choices] = []
|
|
264
|
-
else
|
|
265
|
-
new_arg[:choices] = possible_choices.map { |c| c[1] }
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
# if the choices are inherited from the model, then need to just display the default value which
|
|
269
|
-
# somehow magically works because that is the display name
|
|
270
|
-
if new_arg[:default_value]
|
|
271
|
-
new_arg[:choices] << new_arg[:default_value] unless new_arg[:choices].include?(new_arg[:default_value])
|
|
272
|
-
end
|
|
273
|
-
when "String"
|
|
274
|
-
new_arg[:default_value].gsub!(/"|'/, "") if new_arg[:default_value]
|
|
275
|
-
when "Bool"
|
|
276
|
-
new_arg[:default_value] = new_arg[:default_value].downcase == "true" ? true : false
|
|
277
|
-
when "Integer"
|
|
278
|
-
new_arg[:default_value] = new_arg[:default_value].to_i if new_arg[:default_value]
|
|
279
|
-
when "Double"
|
|
280
|
-
new_arg[:default_value] = new_arg[:default_value].to_f if new_arg[:default_value]
|
|
281
|
-
else
|
|
282
|
-
raise "unknown variable type of #{new_arg[:variable_type]}"
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
measure_hash[:arguments] << new_arg
|
|
286
|
-
end
|
|
287
|
-
|
|
288
293
|
# create a new measure.json file for parsing later if need be
|
|
289
294
|
File.open("#{measure_hash[:path]}/measure.json", 'w') { |f| f << MultiJson.dump(measure_hash, :pretty => true) }
|
|
290
|
-
|
|
291
295
|
end
|
|
292
296
|
else
|
|
293
297
|
puts "Problems downloading #{measure[:measure][:name]}... moving on"
|
|
@@ -296,6 +300,41 @@ module BCL
|
|
|
296
300
|
end
|
|
297
301
|
end
|
|
298
302
|
|
|
303
|
+
# clean name
|
|
304
|
+
def clean(name)
|
|
305
|
+
# TODO: save/display errors
|
|
306
|
+
errors = ""
|
|
307
|
+
m = nil
|
|
308
|
+
|
|
309
|
+
clean_name = name
|
|
310
|
+
# remove everything btw parentheses
|
|
311
|
+
m = clean_name.match(/\((.+?)\)/)
|
|
312
|
+
unless m.nil?
|
|
313
|
+
errors = errors + " removing parentheses,"
|
|
314
|
+
clean_name = clean_name.gsub(/\((.+?)\)/, "")
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# remove everything btw brackets
|
|
318
|
+
m = nil
|
|
319
|
+
m = clean_name.match(/\[(.+?)\]/)
|
|
320
|
+
unless m.nil?
|
|
321
|
+
errors = errors + " removing brackets,"
|
|
322
|
+
clean_name = clean_name.gsub(/\[(.+?)\]/, "")
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# remove characters
|
|
326
|
+
m = nil
|
|
327
|
+
m = clean_name.match(/(\?|\.|\#).+?/)
|
|
328
|
+
unless m.nil?
|
|
329
|
+
errors = errors + " removing any of following: ?.#"
|
|
330
|
+
clean_name = clean_name.gsub(/(\?|\.|\#).+?/, "")
|
|
331
|
+
end
|
|
332
|
+
clean_name = clean_name.gsub(".", "")
|
|
333
|
+
clean_name = clean_name.gsub("?", "")
|
|
334
|
+
|
|
335
|
+
clean_name
|
|
336
|
+
end
|
|
337
|
+
|
|
299
338
|
# retrieve measures for parsing metadata.
|
|
300
339
|
# specify a search term to narrow down search or leave nil to retrieve all
|
|
301
340
|
# set all_pages to true to iterate over all pages of results
|
|
@@ -461,7 +500,7 @@ module BCL
|
|
|
461
500
|
path = "/api/content.json"
|
|
462
501
|
headers = {'Content-Type' => 'application/json', 'Cookie' => @session, 'X-CSRF-Token' => @access_token}
|
|
463
502
|
|
|
464
|
-
res = @http.post(path, @data
|
|
503
|
+
res = @http.post(path, MultiJson.dump(@data), headers)
|
|
465
504
|
|
|
466
505
|
res_j = "could not get json from http post response"
|
|
467
506
|
if res.code == '200'
|
data/lib/bcl/core_ext.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class String
|
|
2
|
+
def to_underscore
|
|
3
|
+
self.gsub(/::/, '/').
|
|
4
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
|
5
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
|
6
|
+
tr("-", "_").
|
|
7
|
+
downcase
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# simple method to create titles
|
|
11
|
+
def titleize
|
|
12
|
+
arr = ['a', 'an', 'the']
|
|
13
|
+
self.gsub('_', ' ').gsub(/\w+/) { |match| arr.include?(match) ? match : match.capitalize }
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/bcl/master_taxonomy.rb
CHANGED
|
@@ -37,7 +37,10 @@ module BCL
|
|
|
37
37
|
|
|
38
38
|
# each TermStruct represents a row in the master taxonomy
|
|
39
39
|
TermStruct = Struct.new(:first_level, :second_level, :third_level, :level_hierarchy, :name, :description,
|
|
40
|
-
:abbr, :data_type, :enums, :ip_written, :ip_symbol, :ip_mask, :si_written, :si_symbol, :si_mask,
|
|
40
|
+
:abbr, :data_type, :enums, :ip_written, :ip_symbol, :ip_mask, :si_written, :si_symbol, :si_mask,
|
|
41
|
+
:unit_conversion, :default_val, :min_val, :max_val, :allow_multiple, :row, :tp_include,
|
|
42
|
+
:tp_required, :tp_use_in_search, :tp_use_in_facets, :tp_show_data_to_data_users, :tp_third_party_testing,
|
|
43
|
+
:tp_additional_web_dev_info, :tp_additional_data_user_info, :tp_additional_data_submitter_info)
|
|
41
44
|
|
|
42
45
|
|
|
43
46
|
# class for parsing, validating, and querying the master taxonomy document
|
data/lib/bcl/tar_ball.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
######################################################################
|
|
2
2
|
# Copyright (c) 2008-2013, Alliance for Sustainable Energy.
|
|
3
3
|
# All rights reserved.
|
|
4
4
|
#
|
|
@@ -21,8 +21,8 @@ module BCL
|
|
|
21
21
|
|
|
22
22
|
module_function
|
|
23
23
|
|
|
24
|
+
# tarball multiple paths recursively to destination
|
|
24
25
|
def tarball(destination, paths)
|
|
25
|
-
|
|
26
26
|
#check for filepath length limit
|
|
27
27
|
full_destination = File.expand_path(destination)
|
|
28
28
|
if full_destination.length > 259 #256 chars max; "C:\" doesn't count
|
|
@@ -45,13 +45,12 @@ module BCL
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def extract_tarball(filename, destination)
|
|
48
|
-
Zlib::GzipReader.open(filename)
|
|
48
|
+
Zlib::GzipReader.open(filename) do |gz|
|
|
49
49
|
Archive::Tar::Minitar.unpack(gz, destination)
|
|
50
|
-
|
|
50
|
+
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def create_zip(destination, paths)
|
|
54
|
-
|
|
55
54
|
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
|
|
56
55
|
paths.each do |fi|
|
|
57
56
|
# Two arguments:
|
|
@@ -60,17 +59,16 @@ module BCL
|
|
|
60
59
|
zipfile.add(fi.basename, fi)
|
|
61
60
|
end
|
|
62
61
|
end
|
|
63
|
-
|
|
64
62
|
end
|
|
65
63
|
|
|
66
64
|
def extract_zip(filename, destination, delete_zip = false)
|
|
67
|
-
Zip::File.open(filename)
|
|
68
|
-
zip_file.each
|
|
65
|
+
Zip::File.open(filename) do |zip_file|
|
|
66
|
+
zip_file.each do |f|
|
|
69
67
|
f_path=File.join(destination, f.name)
|
|
70
68
|
FileUtils.mkdir_p(File.dirname(f_path))
|
|
71
|
-
zip_file.extract(f, f_path) unless File.exist?
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
zip_file.extract(f, f_path) unless File.exist? f_path
|
|
70
|
+
end
|
|
71
|
+
end
|
|
74
72
|
|
|
75
73
|
if delete_zip
|
|
76
74
|
fileList = Array.new
|
|
@@ -79,4 +77,4 @@ module BCL
|
|
|
79
77
|
end
|
|
80
78
|
end
|
|
81
79
|
|
|
82
|
-
end
|
|
80
|
+
end
|
data/lib/bcl/version.rb
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
######################################################################
|
|
2
|
-
# Copyright (c) 2008-2013, Alliance for Sustainable Energy.
|
|
3
|
-
# All rights reserved.
|
|
4
|
-
#
|
|
5
|
-
# This library is free software; you can redistribute it and/or
|
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
-
# License as published by the Free Software Foundation; either
|
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
-
#
|
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
-
# Lesser General Public License for more details.
|
|
14
|
-
#
|
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
-
# License along with this library; if not, write to the Free Software
|
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18
|
-
######################################################################
|
|
19
|
-
|
|
20
|
-
module BCL
|
|
21
|
-
VERSION = "0.5.
|
|
22
|
-
end
|
|
1
|
+
######################################################################
|
|
2
|
+
# Copyright (c) 2008-2013, Alliance for Sustainable Energy.
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# This library is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
+
# License as published by the Free Software Foundation; either
|
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
# License along with this library; if not, write to the Free Software
|
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18
|
+
######################################################################
|
|
19
|
+
|
|
20
|
+
module BCL
|
|
21
|
+
VERSION = "0.5.3"
|
|
22
|
+
end
|
data/lib/bcl.rb
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
require 'pathname'
|
|
2
2
|
require 'base64'
|
|
3
3
|
|
|
4
|
+
begin
|
|
5
|
+
require 'openstudio'
|
|
6
|
+
$openstudio_gem = true
|
|
7
|
+
rescue LoadError => e
|
|
8
|
+
$openstudio_gem = false
|
|
9
|
+
puts 'OpenStudio did not load, but most functionality is still available. Will continue...'
|
|
10
|
+
end
|
|
11
|
+
|
|
4
12
|
# file formatters
|
|
5
13
|
require 'yaml'
|
|
6
14
|
require 'multi_json'
|
|
@@ -12,11 +20,14 @@ require 'archive/tar/minitar'
|
|
|
12
20
|
require 'zlib'
|
|
13
21
|
require 'zip'
|
|
14
22
|
|
|
15
|
-
require '
|
|
23
|
+
require 'rubyXL'
|
|
24
|
+
|
|
25
|
+
require 'bcl/core_ext'
|
|
26
|
+
require 'bcl/base_xml'
|
|
16
27
|
require 'bcl/component_spreadsheet'
|
|
17
|
-
require 'bcl/
|
|
28
|
+
require 'bcl/component_from_spreadsheet'
|
|
29
|
+
require 'bcl/component'
|
|
18
30
|
require 'bcl/component_methods'
|
|
19
|
-
require 'bcl/measure_xml'
|
|
20
31
|
require 'bcl/tar_ball'
|
|
21
32
|
require 'bcl/master_taxonomy'
|
|
22
33
|
require 'bcl/version'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bcl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Macumber
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2014-
|
|
14
|
+
date: 2014-06-16 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: uuid
|
|
@@ -167,6 +167,20 @@ dependencies:
|
|
|
167
167
|
- - '>='
|
|
168
168
|
- !ruby/object:Gem::Version
|
|
169
169
|
version: '0'
|
|
170
|
+
- !ruby/object:Gem::Dependency
|
|
171
|
+
name: rubyXL
|
|
172
|
+
requirement: !ruby/object:Gem::Requirement
|
|
173
|
+
requirements:
|
|
174
|
+
- - '>='
|
|
175
|
+
- !ruby/object:Gem::Version
|
|
176
|
+
version: '0'
|
|
177
|
+
type: :runtime
|
|
178
|
+
prerelease: false
|
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
180
|
+
requirements:
|
|
181
|
+
- - '>='
|
|
182
|
+
- !ruby/object:Gem::Version
|
|
183
|
+
version: '0'
|
|
170
184
|
description: This gem contains helper methods for generating the Component XML file
|
|
171
185
|
needed to upload files to the Building Component Library. It also contains the classes
|
|
172
186
|
needed for logging in via the api and uploading generating components
|
|
@@ -175,14 +189,15 @@ executables: []
|
|
|
175
189
|
extensions: []
|
|
176
190
|
extra_rdoc_files: []
|
|
177
191
|
files:
|
|
178
|
-
- lib/bcl/
|
|
192
|
+
- lib/bcl/base_xml.rb
|
|
193
|
+
- lib/bcl/component.rb
|
|
194
|
+
- lib/bcl/component_from_spreadsheet.rb
|
|
179
195
|
- lib/bcl/component_methods.rb
|
|
180
196
|
- lib/bcl/component_spreadsheet.rb
|
|
181
|
-
- lib/bcl/
|
|
197
|
+
- lib/bcl/core_ext.rb
|
|
182
198
|
- lib/bcl/current_taxonomy.json
|
|
183
199
|
- lib/bcl/current_taxonomy.xml
|
|
184
200
|
- lib/bcl/master_taxonomy.rb
|
|
185
|
-
- lib/bcl/measure_xml.rb
|
|
186
201
|
- lib/bcl/tar_ball.rb
|
|
187
202
|
- lib/bcl/version.rb
|
|
188
203
|
- lib/bcl.rb
|
data/lib/bcl/measure_xml.rb
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
######################################################################
|
|
2
|
-
# Copyright (c) 2008-2013, Alliance for Sustainable Energy.
|
|
3
|
-
# All rights reserved.
|
|
4
|
-
#
|
|
5
|
-
# This library is free software; you can redistribute it and/or
|
|
6
|
-
# modify it under the terms of the GNU Lesser General Public
|
|
7
|
-
# License as published by th e Free Software Foundation; either
|
|
8
|
-
# version 2.1 of the License, or (at your option) any later version.
|
|
9
|
-
#
|
|
10
|
-
# This library is distributed in the hope that it will be useful,
|
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
-
# Lesser General Public License for more details.
|
|
14
|
-
#
|
|
15
|
-
# You should have received a copy of the GNU Lesser General Public
|
|
16
|
-
# License along with this library; if not, write to the Free Software
|
|
17
|
-
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18
|
-
######################################################################
|
|
19
|
-
|
|
20
|
-
# Provides programmatic access to the component.xsd schema needed for
|
|
21
|
-
# generating the component information that will be uploaded to
|
|
22
|
-
# the Building Component Library.
|
|
23
|
-
|
|
24
|
-
module BCL
|
|
25
|
-
class Measure
|
|
26
|
-
def initialize(save_path)
|
|
27
|
-
super(save_path)
|
|
28
|
-
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def read_measure_xml(filepath)
|
|
32
|
-
xmlfile = File.open(filepath, 'r').read
|
|
33
|
-
|
|
34
|
-
@xml = LibXML::XML::Document.string(xmlfile)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|