]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/XML/src/FMI1/fmi1_xml_model_description.c
Merge remote-tracking branch 'origin/master' into release/1.35.1
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / XML / src / FMI1 / fmi1_xml_model_description.c
1 /*
2     Copyright (C) 2012 Modelon AB
3
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the BSD style license.
6
7      This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10     FMILIB_License.txt file for more details.
11
12     You should have received a copy of the FMILIB_License.txt file
13     along with this program. If not, contact Modelon AB <http://www.modelon.com>.
14 */
15
16 #include <stdio.h>
17
18
19 #include <JM/jm_named_ptr.h>
20 #include "fmi1_xml_model_description_impl.h"
21 #include "fmi1_xml_vendor_annotations_impl.h"
22 #include "fmi1_xml_parser.h"
23
24 static const char* module = "FMI1XML";
25
26 fmi1_xml_model_description_t * fmi1_xml_allocate_model_description( jm_callbacks* callbacks) {
27     jm_callbacks* cb;
28     fmi1_xml_model_description_t* md;
29
30     if(callbacks) {
31         cb = callbacks;
32     }
33     else {
34         cb = jm_get_default_callbacks();
35     }
36     md = (fmi1_xml_model_description_t*)cb->malloc(sizeof(fmi1_xml_model_description_t));
37     if(!md) {
38                 jm_log_fatal(cb, module, "Could not allocate memory");
39                 return 0;
40         }
41
42     md->callbacks = cb;
43
44     md->status = fmi1_xml_model_description_enu_empty;
45
46     jm_vector_init(char)( & md->fmi1_xml_standard_version, 0,cb);
47     jm_vector_init(char)(&md->modelName, 0,cb);
48     jm_vector_init(char)(&md->modelIdentifier, 0,cb);
49     jm_vector_init(char)(&md->GUID, 0,cb);
50     jm_vector_init(char)(&md->description, 0,cb);
51     jm_vector_init(char)(&md->author, 0,cb);
52     jm_vector_init(char)(&md->version, 0,cb);
53     jm_vector_init(char)(&md->generationTool, 0,cb);
54     jm_vector_init(char)(&md->generationDateAndTime, 0,cb);
55
56
57     md->namingConvension = fmi1_naming_enu_flat;
58     md->numberOfContinuousStates = 0;
59     md->numberOfEventIndicators = 0;
60
61     md->defaultExperimentStartTime = 0;
62
63     md->defaultExperimentStopTime = 1.0;
64
65     md->defaultExperimentTolerance = FMI1_DEFAULT_EXPERIMENT_TOLERANCE;
66
67     jm_vector_init(jm_voidp)(&md->vendorList, 0, cb);
68
69     jm_vector_init(jm_named_ptr)(&md->unitDefinitions, 0, cb);
70     jm_vector_init(jm_named_ptr)(&md->displayUnitDefinitions, 0, cb);
71
72     fmi1_xml_init_type_definitions(&md->typeDefinitions, cb);
73
74     jm_vector_init(jm_named_ptr)(&md->variablesByName, 0, cb);
75
76         md->variablesOrigOrder = 0;
77
78         md->variablesByVR = 0;
79
80         md->inputVariables = 0;
81
82         md->outputVariables = 0;
83
84     jm_vector_init(jm_string)(&md->descriptions, 0, cb);
85
86     md->fmuKind = fmi1_fmu_kind_enu_me;
87
88     md->capabilities = NULL;
89
90     jm_vector_init(jm_string)(&md->additionalModels, 0, cb);
91
92     jm_vector_init(char)(&md->entryPoint, 0,cb);
93     jm_vector_init(char)(&md->mimeType, 0,cb);
94
95     return md;
96 }
97
98
99
100 void fmi1_xml_clear_model_description( fmi1_xml_model_description_t* md) {
101
102     md->status = fmi1_xml_model_description_enu_empty;
103     jm_vector_free_data(char)(&md->fmi1_xml_standard_version);
104     jm_vector_free_data(char)(&md->modelName);
105     jm_vector_free_data(char)(&md->modelIdentifier);
106     jm_vector_free_data(char)(&md->GUID);
107     jm_vector_free_data(char)(&md->description);
108     jm_vector_free_data(char)(&md->author);
109     jm_vector_free_data(char)(&md->version);
110     jm_vector_free_data(char)(&md->generationTool);
111     jm_vector_free_data(char)(&md->generationDateAndTime);
112
113     md->namingConvension = fmi1_naming_enu_flat;
114     md->numberOfContinuousStates = 0;
115     md->numberOfEventIndicators = 0;
116
117     md->defaultExperimentStartTime = 0;
118
119     md->defaultExperimentStopTime = 0;
120
121     md->defaultExperimentTolerance = 0;
122
123     jm_vector_foreach(jm_voidp)(&md->vendorList, (void(*)(void*))fmi1_xml_vendor_free);
124     jm_vector_free_data(jm_voidp)(&md->vendorList);
125
126     jm_named_vector_free_data(&md->unitDefinitions);
127     jm_named_vector_free_data(&md->displayUnitDefinitions);
128
129     fmi1_xml_free_type_definitions_data(&md->typeDefinitions);
130
131     jm_vector_foreach(jm_named_ptr)(&md->variablesByName, fmi1_xml_free_direct_dependencies);
132     jm_named_vector_free_data(&md->variablesByName);
133         if(md->variablesOrigOrder) {
134                 jm_vector_free(jm_voidp)(md->variablesOrigOrder);
135                 md->variablesOrigOrder = 0;
136         }
137     if(md->variablesByVR) {
138                 jm_vector_free(jm_voidp)(md->variablesByVR);
139                 md->variablesByVR = 0;
140         }
141
142         if(md->inputVariables) {
143                 jm_vector_free(jm_voidp)(md->inputVariables);
144                 md->inputVariables = 0;
145         }
146
147         if(md->outputVariables) {
148                 jm_vector_free(jm_voidp)(md->outputVariables);
149                 md->outputVariables = 0;
150         }
151
152
153     jm_vector_foreach(jm_string)(&md->descriptions, (void(*)(const char*))md->callbacks->free);
154     jm_vector_free_data(jm_string)(&md->descriptions);
155
156     jm_vector_foreach(jm_string)(&md->additionalModels, (void(*)(const char*))md->callbacks->free);
157     jm_vector_free_data(jm_string)(&md->additionalModels);
158
159     jm_vector_free_data(char)(&md->entryPoint);
160     jm_vector_free_data(char)(&md->mimeType);
161
162 }
163
164 int fmi1_xml_is_model_description_empty(fmi1_xml_model_description_t* md) {
165     return (md->status == fmi1_xml_model_description_enu_empty);
166 }
167
168 const char* fmi1_xml_get_last_error(fmi1_xml_model_description_t* md) {
169         return jm_get_last_error(md->callbacks);
170 }
171
172 void fmi1_xml_clear_last_error(fmi1_xml_model_description_t* md) {
173         jm_clear_last_error(md->callbacks);
174
175     /* return (md->status != fmi1_xml_model_description_enu_error); */
176 }
177
178 void fmi1_xml_free_model_description(fmi1_xml_model_description_t* md) {
179     jm_callbacks* cb;
180         if(!md) return;
181         cb = md->callbacks;
182     fmi1_xml_clear_model_description(md);
183     cb->free(md->capabilities);
184     cb->free(md);
185 }
186
187 const char* fmi1_xml_get_model_name(fmi1_xml_model_description_t* md) {
188     return jm_vector_char2string(&md->modelName);
189 }
190
191 const char* fmi1_xml_get_model_identifier(fmi1_xml_model_description_t* md){
192     return jm_vector_char2string(&md->modelIdentifier);
193 }
194
195 const char* fmi1_xml_get_GUID(fmi1_xml_model_description_t* md){
196     return jm_vector_char2string(&md->GUID);
197 }
198
199 const char* fmi1_xml_get_description(fmi1_xml_model_description_t* md){
200     return jm_vector_char2string(&md->description);
201 }
202
203 const char* fmi1_xml_get_author(fmi1_xml_model_description_t* md){
204     return jm_vector_char2string(&md->author);
205 }
206
207 const char* fmi1_xml_get_model_standard_version(fmi1_xml_model_description_t* md){
208     return jm_vector_char2string(&md->fmi1_xml_standard_version);
209 }
210
211
212 const char* fmi1_xml_get_model_version(fmi1_xml_model_description_t* md){
213     return jm_vector_char2string(&md->version);
214 }
215
216 const char* fmi1_xml_get_generation_tool(fmi1_xml_model_description_t* md){
217     return jm_vector_char2string(&md->generationTool);
218 }
219
220 const char* fmi1_xml_get_generation_date_and_time(fmi1_xml_model_description_t* md){
221     return jm_vector_char2string(&md->generationDateAndTime);
222 }
223
224 fmi1_variable_naming_convension_enu_t fmi1_xml_get_naming_convention(fmi1_xml_model_description_t* md) {
225     return md->namingConvension;
226 }
227
228
229 unsigned int fmi1_xml_get_number_of_continuous_states(fmi1_xml_model_description_t* md) {
230     return md->numberOfContinuousStates;
231 }
232
233 unsigned int fmi1_xml_get_number_of_event_indicators(fmi1_xml_model_description_t* md) {
234     return md->numberOfEventIndicators;
235 }
236
237 double fmi1_xml_get_default_experiment_start(fmi1_xml_model_description_t* md) {
238     return md->defaultExperimentStartTime;
239 }
240
241 void fmi1_xml_set_default_experiment_start(fmi1_xml_model_description_t* md, double t){
242     md->defaultExperimentStartTime = t;
243 }
244
245 double fmi1_xml_get_default_experiment_stop(fmi1_xml_model_description_t* md){
246     return md->defaultExperimentStopTime;
247 }
248
249 void fmi1_xml_set_default_experiment_stop(fmi1_xml_model_description_t* md, double t){
250     md->defaultExperimentStopTime = t;
251 }
252
253 double fmi1_xml_get_default_experiment_tolerance(fmi1_xml_model_description_t* md){
254     return md->defaultExperimentTolerance;
255 }
256
257 void fmi1_xml_set_default_experiment_tolerance(fmi1_xml_model_description_t* md, double tol){
258     md->defaultExperimentTolerance = tol;
259 }
260
261 fmi1_xml_vendor_list_t* fmi1_xml_get_vendor_list(fmi1_xml_model_description_t* md) {
262         assert(md);
263     return (fmi1_xml_vendor_list_t*)&md->vendorList;
264 }
265
266 unsigned int  fmi1_xml_get_number_of_vendors(fmi1_xml_vendor_list_t* vl) {
267         if(!vl) {
268                 assert(vl && "Vendor list cannot be NULL");
269                 return 0;
270         }
271     return (unsigned int)jm_vector_get_size(jm_voidp)(&vl->vendors);
272 }
273
274 fmi1_xml_vendor_t* fmi1_xml_get_vendor(fmi1_xml_vendor_list_t* v, unsigned int  index) {
275     jm_vector(jm_voidp)* vl;
276         if(!v) {
277                 assert(v && "Vendor list cannot be NULL");
278                 return 0;
279         }
280         vl = &v->vendors;
281     if(index >= jm_vector_get_size(jm_voidp)(vl)) return 0;
282     return (fmi1_xml_vendor_t*)jm_vector_get_item(jm_voidp)(vl, index);
283 }
284
285 fmi1_xml_unit_definitions_t* fmi1_xml_get_unit_definitions(fmi1_xml_model_description_t* md) {
286     return (fmi1_xml_unit_definitions_t*)(&md->unitDefinitions);
287 }
288
289 unsigned int  fmi1_xml_get_unit_definitions_number(fmi1_xml_unit_definitions_t* ud) {
290         if(!ud) {
291                 assert(ud && "Unit definitions cannot be NULL");
292                 return 0;
293         }
294     return (unsigned int)jm_vector_get_size(jm_named_ptr)(&ud->definitions);
295 }
296
297 fmi1_xml_type_definitions_t* fmi1_xml_get_type_definitions(fmi1_xml_model_description_t* md) {
298         assert(md);
299     return &md->typeDefinitions;
300 }
301
302
303 int fmi1_xml_handle_fmiModelDescription(fmi1_xml_parser_context_t *context, const char* data) {
304     jm_name_ID_map_t namingConventionMap[] = {{"flat",fmi1_naming_enu_flat},{"structured", fmi1_naming_enu_structured},{0,0}};
305     fmi1_xml_model_description_t* md = context->modelDescription;
306     if(!data) {
307         if(context -> currentElmID != fmi1_xml_elmID_none) {
308             fmi1_xml_parse_fatal(context, "fmi1_xml_model_description must be the root XML element");
309             return -1;
310         }
311                 jm_log_verbose(context->callbacks, module, "Parsing XML element fmiModelDescription");
312         /* process the attributes */
313         return (
314                     /* <xs:attribute name="fmiVersion" type="xs:normalizedString" use="required" fixed="1.0"/> */
315                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_fmiVersion, 1, &(md->fmi1_xml_standard_version)) ||
316                     /* <xs:attribute name="modelName" type="xs:normalizedString" use="required"> */
317                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_modelName, 1, &(md->modelName)) ||
318                     /* <xs:attribute name="modelIdentifier" type="xs:normalizedString" use="required"> */
319                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_modelIdentifier, 1, &(md->modelIdentifier)) ||
320                     /* <xs:attribute name="guid" type="xs:normalizedString" use="required"> */
321                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_guid, 1, &(md->GUID)) ||
322                     /* <xs:attribute name="description" type="xs:string"/> */
323                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_description, 0, &(md->description)) ||
324                     /* <xs:attribute name="author" type="xs:string"/> */
325                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_author, 0, &(md->author)) ||
326                     /* <xs:attribute name="version" type="xs:normalizedString"> */
327                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_version, 0, &(md->version)) ||
328                     /* <xs:attribute name="generationTool" type="xs:normalizedString"/> */
329                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_generationTool, 0, &(md->generationTool)) ||
330                     /* <xs:attribute name="generationDateAndTime" type="xs:dateTime"/> */
331                     fmi1_xml_set_attr_string(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_generationDateAndTime, 0, &(md->generationDateAndTime)) ||
332                     /* <xs:attribute name="variableNamingConvention" use="optional" default="flat"> */
333                     fmi1_xml_set_attr_enum(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_variableNamingConvention, 0, (unsigned*)&(md->namingConvension), fmi1_naming_enu_flat, namingConventionMap) ||
334                     /* <xs:attribute name="numberOfContinuousStates" type="xs:unsignedInt" use="required"/> */
335                     fmi1_xml_set_attr_uint(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_numberOfContinuousStates, 1, &(md->numberOfContinuousStates),0) ||
336                     /* <xs:attribute name="numberOfEventIndicators" type="xs:unsignedInt" use="required"/> */
337                     fmi1_xml_set_attr_uint(context, fmi1_xml_elmID_fmiModelDescription, fmi_attr_id_numberOfEventIndicators, 1, &(md->numberOfEventIndicators),0)
338                     );
339     }
340     else {
341         /* don't do anything. might give out a warning if(data[0] != 0) */
342         return 0;
343     }
344 }
345
346 int fmi1_xml_handle_DefaultExperiment(fmi1_xml_parser_context_t *context, const char* data) {
347     if(!data) {
348         fmi1_xml_model_description_t* md = context->modelDescription;
349         /* process the attributes */
350         return (
351         /* <xs:attribute name="startTime" type="xs:double"/> */
352                     fmi1_xml_set_attr_double(context, fmi1_xml_elmID_DefaultExperiment, fmi_attr_id_startTime, 0, &md->defaultExperimentStartTime, 0) ||
353         /* <xs:attribute name="stopTime" type="xs:double"/>  */
354                     fmi1_xml_set_attr_double(context, fmi1_xml_elmID_DefaultExperiment, fmi_attr_id_stopTime, 0, &md->defaultExperimentStopTime, 1) ||
355         /* <xs:attribute name="tolerance" type="xs:double">  */
356                     fmi1_xml_set_attr_double(context, fmi1_xml_elmID_DefaultExperiment, fmi_attr_id_tolerance, 0, &md->defaultExperimentTolerance, FMI1_DEFAULT_EXPERIMENT_TOLERANCE)
357                     );
358     }
359     else {
360         /* don't do anything. might give out a warning if(data[0] != 0) */
361         return 0;
362     }
363     return 0;
364 }
365
366 jm_vector(jm_voidp)* fmi1_xml_get_variables_original_order(fmi1_xml_model_description_t* md) {
367         return md->variablesOrigOrder;
368 }
369
370 jm_vector(jm_named_ptr)* fmi1_xml_get_variables_alphabetical_order(fmi1_xml_model_description_t* md){
371         return &md->variablesByName;
372 }
373
374 jm_vector(jm_voidp)* fmi1_xml_get_variables_vr_order(fmi1_xml_model_description_t* md) {
375         return md->variablesByVR;
376 }
377
378
379 fmi1_xml_variable_t* fmi1_xml_get_variable_by_name(fmi1_xml_model_description_t* md, const char* name) {
380         jm_named_ptr key, *found;
381     key.name = name;
382     found = jm_vector_bsearch(jm_named_ptr)(&md->variablesByName, &key, jm_compare_named);
383         if(!found) return 0;
384         return found->ptr;
385 }
386
387
388 fmi1_xml_variable_t* fmi1_xml_get_variable_by_vr(fmi1_xml_model_description_t* md, fmi1_base_type_enu_t baseType, fmi1_value_reference_t vr) {
389     fmi1_xml_variable_t key;
390     fmi1_xml_variable_t *pkey = &key;
391         fmi1_xml_variable_type_base_t keyType;
392         fmi1_xml_variable_t *v = 0;
393     void ** found;
394         if(!md->variablesByVR) return 0;
395         keyType.structKind = fmi1_xml_type_struct_enu_base;
396         keyType.baseType = baseType;
397         key.typeBase = &keyType;
398         key.vr = vr;
399     key.aliasKind = fmi1_variable_is_not_alias;
400
401     found = jm_vector_bsearch(jm_voidp)(md->variablesByVR,(void**)&pkey, fmi1_xml_compare_vr);
402     if(!found) return 0;
403     v = (fmi1_xml_variable_t*)(*found);
404     return v;
405 }
406
407
408 jm_vector(jm_voidp)* fmi1_xml_get_input_variable_list(fmi1_xml_model_description_t* md) {
409         return md->inputVariables;
410 }