Skip to content

Commit 087f8a1

Browse files
authored
Merge pull request #489 from luke-kiernan/issue-485
get_supplemental_attribute methods with component type input
2 parents 882a77f + 393ab0d commit 087f8a1

File tree

7 files changed

+229
-26
lines changed

7 files changed

+229
-26
lines changed

src/component.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ function _get_supplemental_attributes(
8787
get_supplemental_attribute(mgr, x) for
8888
x in list_associated_supplemental_attribute_uuids(
8989
mgr.associations,
90-
component;
91-
attribute_type = supplemental_attribute_type,
90+
component,
91+
supplemental_attribute_type,
9292
)
9393
]
9494
end
@@ -118,8 +118,8 @@ function _get_supplemental_attributes(
118118
attrs = Vector{supplemental_attribute_type}()
119119
for uuid in list_associated_supplemental_attribute_uuids(
120120
mgr.associations,
121-
component;
122-
attribute_type = supplemental_attribute_type,
121+
component,
122+
supplemental_attribute_type,
123123
)
124124
attribute = get_supplemental_attribute(mgr, uuid)
125125
if filter_func(attribute)

src/supplemental_attribute_associations.jl

Lines changed: 144 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ function has_association(
288288
)
289289
end
290290

291+
# component UUIDS from attribute
291292
const _QUERY_LIST_ASSOCIATED_COMP_UUIDS = """
292293
SELECT DISTINCT component_uuid
293294
FROM $SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME
@@ -309,6 +310,38 @@ function list_associated_component_uuids(
309310
return Base.UUID.(table.component_uuid)
310311
end
311312

313+
# attribute UUIDS from component
314+
const _QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS = """
315+
SELECT DISTINCT attribute_uuid
316+
FROM $SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME
317+
WHERE component_uuid = ?
318+
"""
319+
320+
"""
321+
Return the distinct attribute UUIDs associated with the component.
322+
"""
323+
function list_associated_supplemental_attribute_uuids(
324+
associations::SupplementalAttributeAssociations,
325+
component::InfrastructureSystemsComponent,
326+
::Nothing,
327+
)
328+
params = (string(get_uuid(component)),)
329+
table = Tables.columntable(
330+
_execute_cached(
331+
associations,
332+
_QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS,
333+
params,
334+
),
335+
)
336+
return Base.UUID.(table.attribute_uuid)
337+
end
338+
339+
list_associated_supplemental_attribute_uuids(
340+
associations::SupplementalAttributeAssociations,
341+
component::InfrastructureSystemsComponent,
342+
) = list_associated_supplemental_attribute_uuids(associations, component, nothing)
343+
344+
# component UUIDS from attribute plus component type
312345
const _QUERY_LIST_ASSOCIATED_COMP_UUIDS_BY_C_TYPE = StringTemplates.@template """
313346
SELECT DISTINCT component_uuid
314347
FROM $table_name
@@ -336,6 +369,36 @@ function list_associated_component_uuids(
336369
return Base.UUID.(table.component_uuid)
337370
end
338371

372+
# attribute UUIDS from component plus attribute type
373+
const _QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_A_TYPE =
374+
StringTemplates.@template """
375+
SELECT DISTINCT attribute_uuid
376+
FROM $table_name
377+
WHERE component_uuid = ? AND $attribute_type_clause
378+
"""
379+
380+
"""
381+
Return the distinct attribute UUIDs associated with the component, filter by attribute type.
382+
"""
383+
function list_associated_supplemental_attribute_uuids(
384+
associations::SupplementalAttributeAssociations,
385+
component::InfrastructureSystemsComponent,
386+
attribute_type::Type{<:SupplementalAttribute},
387+
)
388+
params = [string(get_uuid(component))]
389+
attribute_type_clause = _get_type_clause!(params, attribute_type, "attribute_type")
390+
query = StringTemplates.render(
391+
_QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_A_TYPE;
392+
table_name = SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME,
393+
attribute_type_clause = attribute_type_clause,
394+
)
395+
table = Tables.columntable(
396+
_execute_cached(associations, query, params),
397+
)
398+
return Base.UUID.(table.attribute_uuid)
399+
end
400+
401+
# component UUIDS from attribute type driver function
339402
"""
340403
Return the distinct component UUIDs associated with the attribute type.
341404
"""
@@ -352,6 +415,27 @@ function list_associated_component_uuids(
352415
return _list_associated_component_uuids(associations, subtypes)
353416
end
354417

418+
# attribute UUIDS from component type driver function
419+
"""
420+
Return the distinct attribute UUIDs associated with the component type.
421+
"""
422+
function list_associated_supplemental_attribute_uuids(
423+
associations::SupplementalAttributeAssociations,
424+
component_type::Type{<:InfrastructureSystemsComponent},
425+
::Nothing,
426+
)
427+
if isconcretetype(component_type)
428+
return _list_associated_supplemental_attribute_uuids(
429+
associations,
430+
(component_type,),
431+
)
432+
end
433+
434+
subtypes = get_all_concrete_subtypes(component_type)
435+
return _list_associated_supplemental_attribute_uuids(associations, subtypes)
436+
end
437+
438+
# component UUIDS from attribute type plus component type
355439
const _QUERY_LIST_ASSOCIATED_COMP_UUIDS_BY_TYPES = StringTemplates.@template """
356440
SELECT DISTINCT component_uuid
357441
FROM $table_name
@@ -380,6 +464,36 @@ function list_associated_component_uuids(
380464
return Base.UUID.(table.component_uuid)
381465
end
382466

467+
# attribute UUIDS from attribute type plus component type
468+
const _QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_TYPES =
469+
StringTemplates.@template """
470+
SELECT DISTINCT attribute_uuid
471+
FROM $table_name
472+
WHERE $attribute_type_clause AND $component_type_clause
473+
"""
474+
475+
"""
476+
Return the distinct attribute UUIDs associated with the component type, filter by
477+
attribute_type.
478+
"""
479+
function list_associated_supplemental_attribute_uuids(
480+
associations::SupplementalAttributeAssociations,
481+
component_type::Type{<:InfrastructureSystemsComponent},
482+
attribute_type::Type{<:SupplementalAttribute},
483+
)
484+
params = String[]
485+
attribute_type_clause = _get_type_clause!(params, attribute_type, "attribute_type")
486+
component_type_clause = _get_type_clause!(params, component_type, "component_type")
487+
query = StringTemplates.render(
488+
_QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_TYPES;
489+
table_name = SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME,
490+
attribute_type_clause = attribute_type_clause,
491+
component_type_clause = component_type_clause,
492+
)
493+
table = Tables.columntable(_execute_cached(associations, query, params))
494+
return Base.UUID.(table.attribute_uuid)
495+
end
496+
383497
const _QUERY_LIST_ASSOCIATED_PAIR_UUIDS = StringTemplates.@template """
384498
SELECT DISTINCT component_uuid, attribute_uuid
385499
FROM $table_name
@@ -431,6 +545,7 @@ function _get_type_clause!(
431545
return type_clause
432546
end
433547

548+
# component UUIDs from attribute type implementation
434549
const _QUERY_LIST_ASSOCIATED_COMP_UUIDS_BY_ONE_TYPE = """
435550
SELECT DISTINCT component_uuid
436551
FROM $SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME
@@ -468,32 +583,41 @@ function _list_associated_component_uuids(
468583
return Base.UUID.(table.component_uuid)
469584
end
470585

471-
const _QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS = StringTemplates.@template """
472-
SELECT attribute_uuid
473-
FROM $table_name
474-
WHERE $where_clause
475-
"""
586+
# attribute UUIDs from component type implementation
587+
const _QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_ONE_TYPE = """
588+
SELECT DISTINCT attribute_uuid
589+
FROM $SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME
590+
WHERE component_type = ?
476591
"""
477-
Return the supplemental attribute UUIDs associated with the component and attribute type.
592+
593+
const _QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_MULTIPLE_TYPES =
594+
StringTemplates.@template """
595+
SELECT DISTINCT attribute_uuid
596+
FROM $table_name
597+
WHERE component_type IN ($placeholder)
478598
"""
479-
function list_associated_supplemental_attribute_uuids(
599+
600+
function _list_associated_supplemental_attribute_uuids(
480601
associations::SupplementalAttributeAssociations,
481-
component::InfrastructureSystemsComponent;
482-
attribute_type::Union{Nothing, Type{<:SupplementalAttribute}} = nothing,
602+
component_types,
483603
)
484-
c_str = "component_uuid = ?"
485-
params = [string(get_uuid(component))]
486-
if isnothing(attribute_type)
487-
where_clause = c_str
604+
len = length(component_types)
605+
if len == 0
606+
# This would require an abstract type with no subtypes. Just here for completeness.
607+
return Base.UUID[]
608+
elseif len == 1
609+
query = _QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_ONE_TYPE
610+
params = (string(nameof(first(component_types))),)
488611
else
489-
a_str = _get_attribute_type_string!(params, attribute_type)
490-
where_clause = "$c_str AND $a_str"
612+
placeholder = chop(repeat("?,", length(component_types)))
613+
params = Tuple(string(nameof(type)) for type in component_types)
614+
query = StringTemplates.render(
615+
_QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS_BY_MULTIPLE_TYPES;
616+
table_name = SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME,
617+
placeholder = placeholder,
618+
)
491619
end
492-
query = StringTemplates.render(
493-
_QUERY_LIST_ASSOCIATED_SUPPLEMENTAL_ATTRIBUTE_UUIDS;
494-
table_name = SUPPLEMENTAL_ATTRIBUTE_TABLE_NAME,
495-
where_clause = where_clause,
496-
)
620+
497621
table = Tables.columntable(_execute_cached(associations, query, params))
498622
return Base.UUID.(table.attribute_uuid)
499623
end

src/supplemental_attribute_manager.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,18 @@ function list_associated_component_uuids(
248248
return list_associated_component_uuids(mgr.associations, attribute_type, component_type)
249249
end
250250

251+
function list_associated_supplemental_attribute_uuids(
252+
mgr::SupplementalAttributeManager,
253+
component_type::Type{<:InfrastructureSystemsComponent},
254+
attribute_type::Union{Nothing, Type{<:SupplementalAttribute}},
255+
)
256+
return list_associated_supplemental_attribute_uuids(
257+
mgr.associations,
258+
component_type,
259+
attribute_type,
260+
)
261+
end
262+
251263
function serialize(mgr::SupplementalAttributeManager)
252264
return Dict(
253265
"associations" => to_records(mgr.associations),

src/system_data.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,31 @@ function get_associated_components(
10871087
]
10881088
end
10891089

1090+
"""
1091+
Return all supplemental attributes associated with the components of the given type, optionally filtered by `attribute_type`.
1092+
1093+
# Arguments
1094+
- `data::SystemData`: the `SystemData` to search
1095+
- `component_type`::Type{<:InfrastructureSystemsComponent}: Only return attributes
1096+
associated with the components of this type.
1097+
- `attribute_type`::Union{Nothing, Type{<:SupplementalAttribute}}`: Optional, type of the
1098+
attributes to return. Can be concrete or abstract.
1099+
"""
1100+
function get_associated_supplemental_attributes(
1101+
data::SystemData,
1102+
component_type::Type{<:InfrastructureSystemsComponent};
1103+
attribute_type::Union{Nothing, Type{<:SupplementalAttribute}} = nothing,
1104+
)
1105+
return [
1106+
get_supplemental_attribute(data, x) for x in
1107+
list_associated_supplemental_attribute_uuids(
1108+
data.supplemental_attribute_manager,
1109+
component_type,
1110+
attribute_type,
1111+
)
1112+
]
1113+
end
1114+
10901115
"""
10911116
Return all components associated with the attribute that match `component_type`.
10921117

test/test_function_data.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,11 @@ end
209209
end
210210

211211
@testset "Test FunctionData printing" begin
212+
type_prefix = @static VERSION >= v"1.12" ? "" : "@NamedTuple{x::Float64, y::Float64}"
212213
repr_answers = [
213214
"InfrastructureSystems.LinearFunctionData(5.0, 1.0)",
214215
"InfrastructureSystems.QuadraticFunctionData(2.0, 3.0, 4.0)",
215-
"InfrastructureSystems.PiecewiseLinearData(@NamedTuple{x::Float64, y::Float64}[(x = 1.0, y = 1.0), (x = 3.0, y = 5.0), (x = 5.0, y = 10.0)])",
216+
"InfrastructureSystems.PiecewiseLinearData($(type_prefix)[(x = 1.0, y = 1.0), (x = 3.0, y = 5.0), (x = 5.0, y = 10.0)])",
216217
"InfrastructureSystems.PiecewiseStepData([1.0, 3.0, 5.0], [2.0, 2.5])",
217218
]
218219
plain_answers = [

test/test_random_seed.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
IS = InfrastructureSystems
21
@testset "Random Seed" begin
32
@test isa(IS.get_random_seed(), Int)
43
end

test/test_system_data.jl

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,48 @@ end
396396
@test length(attributes) == 0
397397
end
398398

399+
@testset "Test get supplemental attribute from component type" begin
400+
data = IS.SystemData()
401+
402+
attr1 = IS.TestSupplemental(; value = 1.0)
403+
attr2 = IS.TestSupplemental(; value = 2.0)
404+
geo_attr1 = IS.GeographicInfo()
405+
geo_attr2 = IS.GeographicInfo(; geo_json = Dict{String, Any}("foo" => 5))
406+
components_to_attributes = Dict(
407+
(IS.TestComponent, "component1") => [geo_attr1, attr1],
408+
(IS.TestComponent, "component2") => [attr1],
409+
(IS.AdditionalTestComponent, "component3") => [geo_attr1, attr2, geo_attr2],
410+
)
411+
412+
for (comp_info, attributes) in components_to_attributes
413+
component_type, name = comp_info
414+
component = component_type(name, 5)
415+
IS.add_component!(data, component)
416+
for attribute in attributes
417+
IS.add_supplemental_attribute!(data, component, attribute)
418+
end
419+
end
420+
421+
# no duplicate attr1, despite occuring twice.
422+
test_comp_attrs = IS.get_associated_supplemental_attributes(data, IS.TestComponent)
423+
@test length(test_comp_attrs) == 2 && attr1 in test_comp_attrs &&
424+
geo_attr1 in test_comp_attrs
425+
426+
add_test_comp_attrs =
427+
IS.get_associated_supplemental_attributes(data, IS.AdditionalTestComponent)
428+
@test length(add_test_comp_attrs) == 3 && attr2 in add_test_comp_attrs &&
429+
geo_attr1 in add_test_comp_attrs && geo_attr2 in add_test_comp_attrs
430+
431+
# test additional attribute_type kwarg.
432+
add_test_comp_geo_attrs = IS.get_associated_supplemental_attributes(
433+
data,
434+
IS.AdditionalTestComponent;
435+
attribute_type = IS.GeographicInfo,
436+
)
437+
@test length(add_test_comp_geo_attrs) == 2 && geo_attr1 in add_test_comp_geo_attrs &&
438+
geo_attr2 in add_test_comp_geo_attrs
439+
end
440+
399441
@testset "Test retrieval of supplemental_attributes" begin
400442
data = IS.SystemData()
401443
geo_supplemental_attribute = IS.GeographicInfo()

0 commit comments

Comments
 (0)