2020 */
2121#include < boost/throw_exception.hpp>
2222#include " dogen.utility/types/log/logger.hpp"
23+ #include " dogen.utility/types/io/unordered_map_io.hpp"
2324#include " dogen.tracing/types/scoped_tracer.hpp"
2425#include " dogen.variability/types/helpers/configuration_selector.hpp"
26+ #include " dogen.identification/io/entities/logical_id_io.hpp"
2527#include " dogen.logical/io/entities/model_io.hpp"
28+ #include " dogen.logical/types/entities/structural/object.hpp"
29+ #include " dogen.logical/types/entities/structural/primitive.hpp"
30+ #include " dogen.logical/io/entities/structural/technical_space_properties_io.hpp"
2631#include " dogen.logical/types/entities/structural/technical_space_properties.hpp"
27- #include " dogen.logical/types/features/technical_space_properties.hpp"
32+ #include " dogen.logical/types/transforms/transformation_error.hpp"
33+ #include " dogen.logical/types/entities/elements_traversal.hpp"
2834#include " dogen.logical/types/transforms/technical_space_properties_transform.hpp"
2935
3036namespace {
@@ -41,11 +47,161 @@ const std::string duplicate_id("Duplicate ID: ");
4147
4248namespace dogen ::logical::transforms {
4349
50+ boost::optional<entities::structural::technical_space_properties>
51+ technical_space_properties_transform::obtain_properties (
52+ const features::technical_space_properties::feature_group& fg,
53+ entities::element& e) {
54+
55+ const auto id (e.name ().id ());
56+ BOOST_LOG_SEV (lg, debug) << " Procesing element: " << id;
57+
58+ /*
59+ * If we do not have any configuration related to streaming
60+ * operations, there is nothing to do.
61+ */
62+ const auto & cfg (*e.configuration ());
63+ const variability::helpers::configuration_selector s (cfg);
64+ if (!s.has_configuration_point (fg.requires_manual_default_constructor ) &&
65+ !s.has_configuration_point (fg.requires_manual_move_constructor ) &&
66+ !s.has_configuration_point (fg.requires_stream_manipulators )) {
67+ BOOST_LOG_SEV (lg, debug) << " No properties found." ;
68+ return boost::optional<
69+ entities::structural::technical_space_properties>();
70+ }
71+
72+ /*
73+ * Create the properties and slot them into the results container.
74+ */
75+ entities::structural::technical_space_properties r;
76+ const auto scfg (features::technical_space_properties::
77+ make_static_configuration (fg, cfg));
78+ r.requires_manual_default_constructor (
79+ scfg.requires_manual_default_constructor );
80+ r.requires_manual_move_constructor (
81+ scfg.requires_manual_move_constructor );
82+ r.requires_stream_manipulators (scfg.requires_stream_manipulators );
83+
84+ return r;
85+ }
86+
87+ std::unordered_map<identification::entities::logical_id,
88+ entities::structural::technical_space_properties>
89+ technical_space_properties_transform::obtain_properties (
90+ const variability::entities::feature_model& fm,
91+ entities::model& m) {
92+
93+ const auto fg (features::technical_space_properties::make_feature_group (fm));
94+ std::unordered_map<identification::entities::logical_id,
95+ entities::structural::technical_space_properties> r;
96+
97+ entities::elements_traversal (m,
98+ [&](entities::element& e) {
99+ const auto o (obtain_properties (fg, e));
100+ if (!o)
101+ return ;
102+
103+ const auto id (e.name ().id ());
104+ const auto pair (std::make_pair (id, *o));
105+ const auto inserted (r.insert (pair).second );
106+ if (!inserted) {
107+ BOOST_LOG_SEV (lg, error) << duplicate_id << id;
108+ BOOST_THROW_EXCEPTION (
109+ transformation_error (duplicate_id + id.value ()));
110+ }
111+ });
112+ BOOST_LOG_SEV (lg, debug) << " Streaming properties: " << r;
113+ return r;
114+ }
115+
116+ void technical_space_properties_transform::
117+ walk_name_tree (const identification::entities::logical_name_tree& nt,
118+ const bool is_top_level, const std::unordered_map<
119+ identification::entities::logical_id,
120+ entities::structural::technical_space_properties>& src_tsps,
121+ entities::structural::technical_space_properties& dest_tsp) {
122+
123+ for (const auto & c : nt.children ())
124+ walk_name_tree (c, false /* is_top_level*/ , src_tsps, dest_tsp);
125+
126+ if (is_top_level && nt.is_current_simple_type ())
127+ dest_tsp.requires_manual_default_constructor (true );
128+
129+ const auto i (src_tsps.find (nt.current ().id ()));
130+ if (i == src_tsps.end ())
131+ return ;
132+
133+ const auto src_tsp (i->second );
134+ if (src_tsp.requires_stream_manipulators ())
135+ dest_tsp.requires_stream_manipulators (true );
136+
137+ if (!is_top_level)
138+ return ;
139+
140+ if (src_tsp.requires_manual_default_constructor ())
141+ dest_tsp.requires_manual_default_constructor (true );
142+
143+ if (src_tsp.requires_manual_move_constructor ())
144+ dest_tsp.requires_manual_move_constructor (true );
145+ }
146+
147+ entities::structural::technical_space_properties
148+ technical_space_properties_transform::compute_properties (
149+ const std::unordered_map<identification::entities::logical_id,
150+ entities::structural::technical_space_properties>& src_tsps,
151+ const std::list<logical::entities::attribute>& attrs) {
152+
153+ entities::structural::technical_space_properties r;
154+ for (const auto & attr : attrs) {
155+ const auto & nt (attr.parsed_type ());
156+ walk_name_tree (nt, true /* is_top_level*/ , src_tsps, r);
157+ }
158+ return r;
159+ }
160+
161+ void technical_space_properties_transform::populate_properties (
162+ const std::unordered_map<identification::entities::logical_id,
163+ entities::structural::technical_space_properties>& src_tsps,
164+ entities::model& m) {
165+
166+ using identification::entities::model_type;
167+ auto & se (m.structural_elements ());
168+ for (auto & pair : se.objects ()) {
169+ /*
170+ * We only need to generate the properties for elements of the
171+ * target model.
172+ */
173+ auto & e (*pair.second );
174+ if (e.provenance ().model_type () != model_type::target)
175+ continue ;
176+
177+ const auto & attrs (e.local_attributes ());
178+ e.technical_space_properties (compute_properties (src_tsps, attrs));
179+ }
180+
181+ for (auto & pair : se.primitives ()) {
182+ /*
183+ * We only need to generate the properties for elements of the
184+ * target model.
185+ */
186+ auto & p (*pair.second );
187+ if (p.provenance ().model_type () != model_type::target)
188+ continue ;
189+
190+ using logical::entities::attribute;
191+ const std::list<attribute> attrs{ p.value_attribute () };
192+ p.technical_space_properties (compute_properties (src_tsps, attrs));
193+ }
194+ }
195+
44196void technical_space_properties_transform::
45197apply (const context &ctx, entities::model &m) {
46198 tracing::scoped_transform_tracer stp (lg, " technical space properties" ,
47199 transform_id, m.name ().qualified ().dot (), *ctx.tracer (), m);
48200
201+ const auto & fm (*ctx.feature_model ());
202+ const auto src_tsps (obtain_properties (fm, m));
203+ populate_properties (src_tsps, m);
204+
49205 stp.end_transform (m);
50206}
51207
0 commit comments