]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMILibrary/src/XML/src/FMI2/fmi2_xml_model_description.c
7d7ba9184b4a4525c9c8b52fd968464bb3d1bfd1
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / XML / src / FMI2 / fmi2_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 "fmi2_xml_model_description_impl.h"
21 #include "fmi2_xml_model_structure_impl.h"
22 #include "fmi2_xml_parser.h"
23
24 static const char* module = "FMI2XML";
25
26 fmi2_xml_model_description_t * fmi2_xml_allocate_model_description( jm_callbacks* callbacks) {
27     jm_callbacks* cb;
28     fmi2_xml_model_description_t* md;
29
30     if(callbacks) {
31         cb = callbacks;
32     }
33     else {
34         cb = jm_get_default_callbacks();
35     }
36     md = (fmi2_xml_model_description_t*)cb->calloc(1, sizeof(fmi2_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 = fmi2_xml_model_description_enu_empty;
45
46     jm_vector_init(char)( & md->fmi2_xml_standard_version, 0,cb);
47     jm_vector_init(char)(&md->modelName, 0,cb);
48     jm_vector_init(char)(&md->modelIdentifierME, 0,cb);
49     jm_vector_init(char)(&md->modelIdentifierCS, 0,cb);
50     jm_vector_init(char)(&md->GUID, 0,cb);
51     jm_vector_init(char)(&md->description, 0,cb);
52     jm_vector_init(char)(&md->author, 0,cb);
53     jm_vector_init(char)(&md->license, 0,cb);
54     jm_vector_init(char)(&md->copyright, 0,cb);
55     jm_vector_init(char)(&md->version, 0,cb);
56     jm_vector_init(char)(&md->generationTool, 0,cb);
57     jm_vector_init(char)(&md->generationDateAndTime, 0,cb);
58
59
60     md->namingConvension = fmi2_naming_enu_flat;
61     md->numberOfContinuousStates = 0;
62     md->numberOfEventIndicators = 0;
63
64     md->defaultExperimentStartTime = 0;
65
66     md->defaultExperimentStopTime = 1.0;
67
68     md->defaultExperimentTolerance = FMI2_DEFAULT_EXPERIMENT_TOLERANCE;
69
70     md->defaultExperimentStepSize = FMI2_DEFAULT_EXPERIMENT_STEPSIZE;
71
72     jm_vector_init(jm_string)(&md->sourceFilesME, 0, cb);
73         jm_vector_init(jm_string)(&md->sourceFilesCS, 0, cb);
74
75         jm_vector_init(jm_string)(&md->vendorList, 0, cb);
76         jm_vector_init(jm_string)(&md->logCategories, 0, cb);
77         jm_vector_init(jm_string)(&md->logCategoryDescriptions, 0, cb);
78
79     jm_vector_init(jm_named_ptr)(&md->unitDefinitions, 0, cb);
80     jm_vector_init(jm_named_ptr)(&md->displayUnitDefinitions, 0, cb);
81
82     fmi2_xml_init_type_definitions(&md->typeDefinitions, cb);
83
84     jm_vector_init(jm_named_ptr)(&md->variablesByName, 0, cb);
85
86         md->variablesOrigOrder = 0;
87
88         md->variablesByVR = 0;
89
90     jm_vector_init(jm_string)(&md->descriptions, 0, cb);
91
92     md->fmuKind = fmi2_fmu_kind_unknown;
93
94         {
95                 int i = fmi2_capabilities_Num;
96                 while(i > 0)
97                         md->capabilities[--i] = 0;
98                 md->capabilities[fmi2_me_completedEventIterationIsProvided] = 1;
99         }
100     return md;
101 }
102
103
104
105 void fmi2_xml_clear_model_description( fmi2_xml_model_description_t* md) {
106
107     md->status = fmi2_xml_model_description_enu_empty;
108     jm_vector_free_data(char)(&md->fmi2_xml_standard_version);
109     jm_vector_free_data(char)(&md->modelName);
110     jm_vector_free_data(char)(&md->modelIdentifierME);
111     jm_vector_free_data(char)(&md->modelIdentifierCS);
112     jm_vector_free_data(char)(&md->GUID);
113     jm_vector_free_data(char)(&md->description);
114     jm_vector_free_data(char)(&md->author);
115     jm_vector_free_data(char)(&md->license);
116     jm_vector_free_data(char)(&md->copyright);
117     jm_vector_free_data(char)(&md->version);
118     jm_vector_free_data(char)(&md->generationTool);
119     jm_vector_free_data(char)(&md->generationDateAndTime);
120
121     md->namingConvension = fmi2_naming_enu_flat;
122     md->numberOfContinuousStates = 0;
123     md->numberOfEventIndicators = 0;
124
125     md->defaultExperimentStartTime = 0;
126
127     md->defaultExperimentStopTime = 0;
128
129     md->defaultExperimentTolerance = 0;
130
131     md->defaultExperimentStepSize = 0;
132
133     jm_vector_foreach(jm_string)(&md->sourceFilesME, (void(*)(const char*))md->callbacks->free);
134     jm_vector_free_data(jm_string)(&md->sourceFilesME); 
135
136     jm_vector_foreach(jm_string)(&md->sourceFilesCS, (void(*)(const char*))md->callbacks->free);
137     jm_vector_free_data(jm_string)(&md->sourceFilesCS); 
138
139     jm_vector_foreach(jm_string)(&md->vendorList, (void(*)(const char*))md->callbacks->free);
140     jm_vector_free_data(jm_string)(&md->vendorList);
141
142     jm_vector_foreach(jm_string)(&md->logCategories, (void(*)(const char*))md->callbacks->free);
143     jm_vector_free_data(jm_string)(&md->logCategories); 
144
145     jm_vector_foreach(jm_string)(&md->logCategoryDescriptions, (void(*)(const char*))md->callbacks->free);
146     jm_vector_free_data(jm_string)(&md->logCategoryDescriptions);       
147
148     jm_named_vector_free_data(&md->unitDefinitions);
149     jm_named_vector_free_data(&md->displayUnitDefinitions);
150
151     fmi2_xml_free_type_definitions_data(&md->typeDefinitions);
152
153     jm_named_vector_free_data(&md->variablesByName);
154         if(md->variablesOrigOrder) {
155                 jm_vector_free(jm_voidp)(md->variablesOrigOrder);
156                 md->variablesOrigOrder = 0;
157         }
158     if(md->variablesByVR) {
159                 jm_vector_free(jm_voidp)(md->variablesByVR);
160                 md->variablesByVR = 0;
161         }
162
163     jm_vector_foreach(jm_string)(&md->descriptions, (void(*)(const char*))md->callbacks->free);
164     jm_vector_free_data(jm_string)(&md->descriptions);
165
166         fmi2_xml_free_model_structure(md->modelStructure);
167         md->modelStructure = 0;
168 }
169
170 int fmi2_xml_is_model_description_empty(fmi2_xml_model_description_t* md) {
171     return (md->status == fmi2_xml_model_description_enu_empty);
172 }
173
174 const char* fmi2_xml_get_last_error(fmi2_xml_model_description_t* md) {
175         return jm_get_last_error(md->callbacks);
176 }
177
178 void fmi2_xml_clear_last_error(fmi2_xml_model_description_t* md) {
179         jm_clear_last_error(md->callbacks);
180     
181     /* return (md->status != fmi2_xml_model_description_enu_error); */
182 }
183
184 void fmi2_xml_free_model_description(fmi2_xml_model_description_t* md) {
185     jm_callbacks* cb;
186         if(!md) return;
187         cb = md->callbacks;
188     fmi2_xml_clear_model_description(md);
189     cb->free(md);
190 }
191
192 const char* fmi2_xml_get_model_name(fmi2_xml_model_description_t* md) {
193     return jm_vector_char2string(&md->modelName);
194 }
195
196 const char* fmi2_xml_get_model_identifier_ME(fmi2_xml_model_description_t* md){
197     return jm_vector_char2string(&md->modelIdentifierME);
198 }
199
200 const char* fmi2_xml_get_model_identifier_CS(fmi2_xml_model_description_t* md){
201     return jm_vector_char2string(&md->modelIdentifierCS);
202 }
203
204 const char* fmi2_xml_get_GUID(fmi2_xml_model_description_t* md){
205     return jm_vector_char2string(&md->GUID);
206 }
207
208 const char* fmi2_xml_get_description(fmi2_xml_model_description_t* md){
209     return jm_vector_char2string(&md->description);
210 }
211
212 const char* fmi2_xml_get_author(fmi2_xml_model_description_t* md){
213     return jm_vector_char2string(&md->author);
214 }
215
216 const char* fmi2_xml_get_license(fmi2_xml_model_description_t* md){
217     return jm_vector_char2string(&md->license);
218 }
219
220 const char* fmi2_xml_get_copyright(fmi2_xml_model_description_t* md){
221     return jm_vector_char2string(&md->copyright);
222 }
223
224 const char* fmi2_xml_get_model_standard_version(fmi2_xml_model_description_t* md){
225     return jm_vector_char2string(&md->fmi2_xml_standard_version);
226 }
227
228
229 const char* fmi2_xml_get_model_version(fmi2_xml_model_description_t* md){
230     return jm_vector_char2string(&md->version);
231 }
232
233 const char* fmi2_xml_get_generation_tool(fmi2_xml_model_description_t* md){
234     return jm_vector_char2string(&md->generationTool);
235 }
236
237 const char* fmi2_xml_get_generation_date_and_time(fmi2_xml_model_description_t* md){
238     return jm_vector_char2string(&md->generationDateAndTime);
239 }
240
241 fmi2_variable_naming_convension_enu_t fmi2_xml_get_naming_convention(fmi2_xml_model_description_t* md) {
242     return md->namingConvension;
243 }
244
245
246 size_t fmi2_xml_get_number_of_continuous_states(fmi2_xml_model_description_t* md) {
247     return md->numberOfContinuousStates;
248 }
249
250 size_t fmi2_xml_get_number_of_event_indicators(fmi2_xml_model_description_t* md) {
251     return md->numberOfEventIndicators;
252 }
253
254 double fmi2_xml_get_default_experiment_start(fmi2_xml_model_description_t* md) {
255     return md->defaultExperimentStartTime;
256 }
257
258 double fmi2_xml_get_default_experiment_stop(fmi2_xml_model_description_t* md){
259     return md->defaultExperimentStopTime;
260 }
261
262 double fmi2_xml_get_default_experiment_tolerance(fmi2_xml_model_description_t* md){
263     return md->defaultExperimentTolerance;
264 }
265
266 double fmi2_xml_get_default_experiment_step(fmi2_xml_model_description_t* md){
267     return md->defaultExperimentStepSize;
268 }
269
270 fmi2_fmu_kind_enu_t fmi2_xml_get_fmu_kind(fmi2_xml_model_description_t* md) {
271         return md->fmuKind;
272 }
273
274 unsigned int* fmi2_xml_get_capabilities(fmi2_xml_model_description_t* md) {
275         return md->capabilities;
276 }
277
278 unsigned int fmi2_xml_get_capability(fmi2_xml_model_description_t* md, fmi2_capabilities_enu_t id) {
279         assert((unsigned)id < (unsigned)fmi2_capabilities_Num);
280         return md->capabilities[id];
281 }
282
283 fmi2_xml_unit_definitions_t* fmi2_xml_get_unit_definitions(fmi2_xml_model_description_t* md) {
284     return (fmi2_xml_unit_definitions_t*)(&md->unitDefinitions);
285 }
286
287 unsigned int  fmi2_xml_get_unit_definitions_number(fmi2_xml_unit_definitions_t* ud) {
288         if(!ud) {
289                 assert(ud && "Unit definitions cannot be NULL");
290                 return 0;
291         }
292     return (unsigned int)jm_vector_get_size(jm_named_ptr)(&ud->definitions);
293 }
294
295 fmi2_xml_type_definitions_t* fmi2_xml_get_type_definitions(fmi2_xml_model_description_t* md) {
296         assert(md);
297     return &md->typeDefinitions;
298 }
299
300 /** \brief Get the number of vendors that had annotations in the XML*/
301 size_t fmi2_xml_get_vendors_num(fmi2_xml_model_description_t* md) {
302         assert(md);
303         return jm_vector_get_size(jm_string)(&md->vendorList);
304 }
305
306 jm_vector(jm_string)* fmi2_xml_get_log_categories(fmi2_xml_model_description_t* md) {
307         assert(md);
308         return &md->logCategories;
309 }
310
311 jm_vector(jm_string)* fmi2_xml_get_log_category_descriptions(fmi2_xml_model_description_t* md) {
312         assert(md);
313         return &md->logCategoryDescriptions;
314 }
315
316 jm_vector(jm_string)* fmi2_xml_get_source_files_me(fmi2_xml_model_description_t* md) {
317         assert(md);
318         return &md->sourceFilesME;
319 }
320
321 jm_vector(jm_string)* fmi2_xml_get_source_files_cs(fmi2_xml_model_description_t* md) {
322         assert(md);
323         return &md->sourceFilesCS;
324 }
325
326 fmi2_xml_model_structure_t* fmi2_xml_get_model_structure(fmi2_xml_model_description_t* md) {
327         assert(md);
328         return md->modelStructure;
329 }
330
331
332 /** \brief Get the name of the vendor with that had annotations in the XML by index */
333 const char* fmi2_xml_get_vendor_name(fmi2_xml_model_description_t* md, size_t  index) {
334         assert(fmi2_xml_get_vendors_num(md) > index);
335
336         return jm_vector_get_item(jm_string)(&md->vendorList,index);
337 }
338
339 int fmi2_xml_is_valid_model_ID_char(char ch) {
340         return ((( ch >= 'A') && (ch <= 'Z')) || 
341                         (( ch >= 'a') && (ch <= 'z')) || 
342                         (ch == '_'));
343 }
344
345 int fmi2_xml_is_valid_model_ID(const char* str) {
346         size_t i, len = strlen(str);
347         char ch = str[0];
348         if( !fmi2_xml_is_valid_model_ID_char(ch)) return 0;
349         for(i = 1; i < len; i++) {
350                 ch = str[i];
351                 if( !fmi2_xml_is_valid_model_ID_char(ch) && (ch < '0') && (ch > '9')) return 0;
352         }
353         return 1;
354 }
355
356 int fmi2_xml_handle_fmiModelDescription(fmi2_xml_parser_context_t *context, const char* data) {
357     jm_name_ID_map_t namingConventionMap[] = {{"flat",fmi2_naming_enu_flat},{"structured", fmi2_naming_enu_structured},{0,0}};
358     fmi2_xml_model_description_t* md = context->modelDescription;
359     if(!data) {
360                 unsigned int numEventIndicators=0;
361                 int ret;
362         if(context -> currentElmID != fmi2_xml_elmID_none) {
363             fmi2_xml_parse_fatal(context, "fmi2_xml_model_description must be the root XML element");
364             return -1;
365         }
366                 jm_log_verbose(context->callbacks, module, "Parsing XML element fmiModelDescription");
367                 md->fmuKind = fmi2_fmu_kind_unknown;
368         /* process the attributes */
369                 ret =        /* <xs:attribute name="fmiVersion" type="xs:normalizedString" use="required" fixed="2.0"/> */
370                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_fmiVersion, 1, &(md->fmi2_xml_standard_version)) ||
371                     /* <xs:attribute name="modelName" type="xs:normalizedString" use="required"> */
372                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_modelName, 1, &(md->modelName)) ||
373                                         /* <xs:attribute name="guid" type="xs:normalizedString" use="required"> */
374                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_guid, 1, &(md->GUID)) ||
375                     /* <xs:attribute name="description" type="xs:string"/> */
376                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_description, 0, &(md->description)) ||
377                     /* <xs:attribute name="author" type="xs:string"/> */
378                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_author, 0, &(md->author)) ||
379                     /* <xs:attribute name="version" type="xs:normalizedString"> */
380                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_version, 0, &(md->version)) ||
381                                 /* <xs:attribute name="copyright" type="xs:string"> */
382                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_copyright, 0, &(md->copyright)) ||
383                                         /* <xs:attribute name="license" type="xs:string"> */
384                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_license, 0, &(md->license)) ||
385                                         /* <xs:attribute name="generationTool" type="xs:normalizedString"/> */
386                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_generationTool, 0, &(md->generationTool)) ||
387                     /* <xs:attribute name="generationDateAndTime" type="xs:dateTime"/> */
388                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_generationDateAndTime, 0, &(md->generationDateAndTime)) ||
389                     /* <xs:attribute name="variableNamingConvention" use="optional" default="flat"> */
390                     fmi2_xml_set_attr_enum(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_variableNamingConvention, 0, (unsigned*)&(md->namingConvension), fmi2_naming_enu_flat, namingConventionMap) ||
391                     /* <xs:attribute name="numberOfEventIndicators" type="xs:unsignedInt"/> */
392                     fmi2_xml_set_attr_uint(context, fmi2_xml_elmID_fmiModelDescription, fmi_attr_id_numberOfEventIndicators, 0, &numEventIndicators,0);
393                                         md->numberOfEventIndicators = numEventIndicators;
394                 return (ret );
395     }
396     else {
397                 /* check that fmuKind is defined and that model identifies are valid*/
398                 if(md->fmuKind == fmi2_fmu_kind_unknown) {
399                         fmi2_xml_parse_fatal(context, "Neither ModelExchange nor CoSimulation element were parsed correctly. FMU kind not known.");
400                         return -1;
401                 }
402                 if( (md->fmuKind != fmi2_fmu_kind_cs) && !fmi2_xml_is_valid_model_ID(fmi2_xml_get_model_identifier_ME(md))) {
403                         fmi2_xml_parse_error(context, "Model identifier '%s' is not valid (must be a valid C-identifier)", fmi2_xml_get_model_identifier_ME(md));
404                         return -1;
405                 }
406                 if( (md->fmuKind != fmi2_fmu_kind_me) && !fmi2_xml_is_valid_model_ID(fmi2_xml_get_model_identifier_CS(md))) {
407                         fmi2_xml_parse_error(context, "Model identifier '%s' is not valid (must be a valid C-identifier)", fmi2_xml_get_model_identifier_CS(md));
408                         return -1;
409                 }
410                 if( (md->fmuKind == fmi2_fmu_kind_me_and_cs) && (strcmp(fmi2_xml_get_model_identifier_CS(md), fmi2_xml_get_model_identifier_ME(md)) == 0)) {
411                         jm_log_info(context->callbacks,module, "Found model identifiers for ModelExchange and CoSimulation");
412                         return 1;
413                 }
414                 if(!md->modelStructure) {
415                         fmi2_xml_parse_fatal(context, "No model structure information available. Cannot continue.");
416                         return -1;
417                 }
418         return 0;
419     }
420 }
421
422 int fmi2_xml_handle_ModelExchange(fmi2_xml_parser_context_t *context, const char* data) {
423     fmi2_xml_model_description_t* md = context->modelDescription;
424     if(!data) {
425                 jm_log_verbose(context->callbacks, module, "Parsing XML element ModelExchange");
426
427         /*  reset handles for the elements that are specific under ModelExchange */
428         fmi2_xml_set_element_handle(context, "SourceFiles", FMI2_XML_ELM_ID(SourceFiles));
429         fmi2_xml_set_element_handle(context, "File", FMI2_XML_ELM_ID(File));
430
431                 md->fmuKind = fmi2_fmu_kind_me;
432         /* process the attributes */
433
434         /* <xs:attribute name="providesDirectionalDerivative" type="xs:boolean" default="false"/> */
435         if (fmi2_xml_is_attr_defined(context, fmi_attr_id_providesDirectionalDerivatives)) {
436                         fmi2_xml_parse_error(context, "Attribute 'providesDirectionalDerivatives' has been renamed to 'providesDirectionalDerivative'.");
437             if (fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_providesDirectionalDerivatives,0,
438                 &md->capabilities[fmi2_me_providesDirectionalDerivatives],0)) return -1;
439         }
440         else {
441             if (fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_providesDirectionalDerivative,0,
442                 &md->capabilities[fmi2_me_providesDirectionalDerivatives],0)) return -1;
443         }
444
445         return (        /* <xs:attribute name="modelIdentifier" type="xs:normalizedString" use="required"> */
446                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_ModelExchange, fmi_attr_id_modelIdentifier, 1, &(md->modelIdentifierME)) ||
447                                         /*      <xs:attribute name="needsExecutionTool" type="xs:boolean" default="false"> */
448                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_needsExecutionTool,0,
449                                              &md->capabilities[fmi2_me_needsExecutionTool],0) ||
450                                         /* <xs:attribute name="completedIntegratorStepNotNeeded" type="xs:boolean" default="false"/> */
451                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_completedIntegratorStepNotNeeded,0,
452                                              &md->capabilities[fmi2_me_completedIntegratorStepNotNeeded],0) ||
453                                         /* <xs:attribute name="canBeInstantiatedOnlyOncePerProcess" type="xs:boolean" default="false"/> */
454                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_canBeInstantiatedOnlyOncePerProcess,0,
455                                              &md->capabilities[fmi2_me_canBeInstantiatedOnlyOncePerProcess],0) ||
456                                         /* <xs:attribute name="canNotUseMemoryManagementFunctions" type="xs:boolean" default="false"/> */
457                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_canNotUseMemoryManagementFunctions,0,
458                                              &md->capabilities[fmi2_me_canNotUseMemoryManagementFunctions],0) ||
459                                         /* <xs:attribute name="canGetAndSetFMUstate" type="xs:boolean" default="false"/> */
460                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_canGetAndSetFMUstate,0,
461                                              &md->capabilities[fmi2_me_canGetAndSetFMUstate],0) ||
462                                         /* <xs:attribute name="canSerializeFMUstate" type="xs:boolean" default="false"/> */
463                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_ModelExchange, fmi_attr_id_canSerializeFMUstate,0,
464                                              &md->capabilities[fmi2_me_canSerializeFMUstate],0)
465                    );
466     }
467     else {
468         /* don't do anything. might give out a warning if(data[0] != 0) */
469         return 0;
470     }
471 }
472
473 int fmi2_xml_handle_CoSimulation(fmi2_xml_parser_context_t *context, const char* data) {
474     fmi2_xml_model_description_t* md = context->modelDescription;
475     if(!data) {
476                 jm_log_verbose(context->callbacks, module, "Parsing XML element CoSimulation");
477
478         /*  reset handles for the elements that are specific under CoSimulation */
479         fmi2_xml_set_element_handle(context, "SourceFiles", FMI2_XML_ELM_ID(SourceFilesCS));
480         fmi2_xml_set_element_handle(context, "File", FMI2_XML_ELM_ID(FileCS));
481
482                 if(md->fmuKind == fmi2_fmu_kind_me)
483                         md->fmuKind = fmi2_fmu_kind_me_and_cs;
484                 else
485                         md->fmuKind = fmi2_fmu_kind_cs;
486         /* process the attributes */
487
488         /* <xs:attribute name="providesDirectionalDerivative" type="xs:boolean" default="false"/> */
489         if (fmi2_xml_is_attr_defined(context, fmi_attr_id_providesDirectionalDerivatives)) {
490                         fmi2_xml_parse_error(context, "Attribute 'providesDirectionalDerivatives' has been renamed to 'providesDirectionalDerivative'.");
491             if (fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_providesDirectionalDerivatives,0,
492                 &md->capabilities[fmi2_cs_providesDirectionalDerivatives],0)) return -1;
493         }
494         else {
495             if (fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_providesDirectionalDerivative,0,
496                 &md->capabilities[fmi2_cs_providesDirectionalDerivatives],0)) return -1;
497         }
498
499         return (        /* <xs:attribute name="modelIdentifier" type="xs:normalizedString" use="required"> */
500                     fmi2_xml_set_attr_string(context, fmi2_xml_elmID_CoSimulation, fmi_attr_id_modelIdentifier, 1, &(md->modelIdentifierCS)) ||
501                                         /*      <xs:attribute name="needsExecutionTool" type="xs:boolean" default="false"> */
502                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_needsExecutionTool,0,
503                                              &md->capabilities[fmi2_cs_needsExecutionTool],0) ||
504                                         /* <xs:attribute name="canHandleVariableCommunicationStepSize" type="xs:boolean" default="false"/> */
505                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_canHandleVariableCommunicationStepSize,0,
506                                              &md->capabilities[fmi2_cs_canHandleVariableCommunicationStepSize],0) ||
507                                         /* <xs:attribute name="canInterpolateInputs" type="xs:boolean" default="false"/>*/
508                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_canInterpolateInputs,0,
509                                              &md->capabilities[fmi2_cs_canInterpolateInputs],0) ||
510                                         /* <xs:attribute name="maxOutputDerivativeOrder" type="xs:unsignedInt" default="0"/> */
511                     fmi2_xml_set_attr_uint(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_maxOutputDerivativeOrder,0,
512                                              &md->capabilities[fmi2_cs_maxOutputDerivativeOrder],0) ||
513                                         /* <xs:attribute name="canRunAsynchronuously" type="xs:boolean" default="false"/> */
514                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_canRunAsynchronuously,0,
515                                              &md->capabilities[fmi2_cs_canRunAsynchronuously],0) ||
516                                         /* <xs:attribute name="canBeInstantiatedOnlyOncePerProcess" type="xs:boolean" default="false"/> */
517                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_canBeInstantiatedOnlyOncePerProcess,0,
518                                              &md->capabilities[fmi2_cs_canBeInstantiatedOnlyOncePerProcess],0) ||
519                                         /* <xs:attribute name="canNotUseMemoryManagementFunctions" type="xs:boolean" default="false"/> */
520                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_canNotUseMemoryManagementFunctions,0,
521                                              &md->capabilities[fmi2_cs_canNotUseMemoryManagementFunctions],0) ||
522                                         /* <xs:attribute name="canGetAndSetFMUstate" type="xs:boolean" default="false"/> */
523                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_canGetAndSetFMUstate,0,
524                                              &md->capabilities[fmi2_cs_canGetAndSetFMUstate],0) ||
525                                         /* <xs:attribute name="canSerializeFMUstate" type="xs:boolean" default="false"/> */
526                     fmi2_xml_set_attr_boolean(context,fmi2_xml_elmID_CoSimulation, fmi_attr_id_canSerializeFMUstate,0,
527                                              &md->capabilities[fmi2_cs_canSerializeFMUstate],0) 
528                    );
529     }
530     else {
531         /* don't do anything. might give out a warning if(data[0] != 0) */
532         return 0;
533     }
534 }
535
536 int fmi2_xml_handle_SourceFiles(fmi2_xml_parser_context_t *context, const char* data) {
537     return 0;
538 }
539
540 static int push_back_jm_string(fmi2_xml_parser_context_t *context, jm_vector(jm_string) *stringvector, jm_vector(char)* buf) {
541     size_t len;
542     char* string = 0;
543     jm_string *pstring;
544
545     pstring = jm_vector_push_back(jm_string)(stringvector, string);
546         len = jm_vector_get_size(char)(buf);
547     if(pstring )
548         *pstring = string = (char*)(context->callbacks->malloc(len + 1));
549         if(!pstring || !string) {
550             fmi2_xml_parse_fatal(context, "Could not allocate memory");
551                 return -1;
552         }
553     if (len != 0) { /* No need to memcpy empty strings (gives assetion error) */ 
554         memcpy(string, jm_vector_get_itemp(char)(buf,0), len);
555     }
556     string[len] = 0;
557     return 0;
558 }
559
560
561 int fmi2_xml_handle_File(fmi2_xml_parser_context_t *context, const char* data) {
562     if(!data) {
563         fmi2_xml_model_description_t* md = context->modelDescription;
564         jm_vector(char)* bufName = fmi2_xml_reserve_parse_buffer(context,1,100);
565
566         if(!bufName) return -1;
567         /* <xs:attribute name="name" type="xs:normalizedString" use="required"> */\r
568         if( fmi2_xml_set_attr_string(context, fmi2_xml_elmID_File, fmi_attr_id_name, 1, bufName))
569             return -1;
570         return push_back_jm_string(context, &md->sourceFilesME, bufName);
571     }
572     else {
573         return 0;
574     }
575 }
576
577 int fmi2_xml_handle_SourceFilesCS(fmi2_xml_parser_context_t *context, const char* data) {
578     return 0;
579 }
580
581 int fmi2_xml_handle_FileCS(fmi2_xml_parser_context_t *context, const char* data) {
582     if(!data) {
583         fmi2_xml_model_description_t* md = context->modelDescription;
584         jm_vector(char)* bufName = fmi2_xml_reserve_parse_buffer(context,1,100);
585
586         if(!bufName) return -1;
587         /* <xs:attribute name="name" type="xs:normalizedString" use="required"> */\r
588         if( fmi2_xml_set_attr_string(context, fmi2_xml_elmID_File, fmi_attr_id_name, 1, bufName))
589             return -1;
590         return push_back_jm_string(context, &md->sourceFilesCS, bufName);
591     }
592     else {
593         return 0;
594     }
595 }
596
597 int fmi2_xml_handle_LogCategories(fmi2_xml_parser_context_t *context, const char* data) {
598 /*    fmi2_xml_model_description_t* md = context->modelDescription; */
599     if(!data) {
600                 jm_log_verbose(context->callbacks, module, "Parsing XML element LogCategories");
601         /* process the attributes */
602         return (0);
603     }
604     else {
605         /* don't do anything. might give out a warning if(data[0] != 0) */
606         return 0;
607     }
608 }
609
610 int fmi2_xml_handle_Category(fmi2_xml_parser_context_t *context, const char* data) {
611     if(!data) {
612         /* process the attributes */
613         fmi2_xml_model_description_t* md = context->modelDescription;
614         jm_vector(char)* bufName = fmi2_xml_reserve_parse_buffer(context,1,100);
615
616         if (!bufName) return -1;
617                 /* <xs:attribute name="name" type="xs:normalizedString"> */
618         if (fmi2_xml_set_attr_string(context, fmi2_xml_elmID_Category, fmi_attr_id_name, 1, bufName))
619                         return -1;
620         if (push_back_jm_string(context, &md->logCategories, bufName) < 0) return -1;
621
622         if (fmi2_xml_set_attr_string(context, fmi2_xml_elmID_Category, fmi_attr_id_description, 0, bufName) < 0) return -1;
623         if (push_back_jm_string(context, &md->logCategoryDescriptions, bufName) < 0) return -1;
624         return 0;
625     }
626     else {
627         /* don't do anything. might give out a warning if(data[0] != 0) */
628         return 0;
629     }
630 }
631
632 int fmi2_xml_handle_DefaultExperiment(fmi2_xml_parser_context_t *context, const char* data) {
633     if(!data) {
634         fmi2_xml_model_description_t* md = context->modelDescription;
635         /* process the attributes */
636         return (
637         /* <xs:attribute name="startTime" type="xs:double"/> */
638                 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_DefaultExperiment, fmi_attr_id_startTime, 0, &md->defaultExperimentStartTime, 0) ||
639         /* <xs:attribute name="stopTime" type="xs:double"/>  */
640                 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_DefaultExperiment, fmi_attr_id_stopTime, 0, &md->defaultExperimentStopTime, 1) ||
641         /* <xs:attribute name="tolerance" type="xs:double">  */
642                 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_DefaultExperiment, fmi_attr_id_tolerance, 0, &md->defaultExperimentTolerance, FMI2_DEFAULT_EXPERIMENT_TOLERANCE) ||
643         /* <xs:attribute name="stepSize" type="xs:double">   */
644                 fmi2_xml_set_attr_double(context, fmi2_xml_elmID_DefaultExperiment, fmi_attr_id_stepSize, 0, &md->defaultExperimentStepSize, FMI2_DEFAULT_EXPERIMENT_STEPSIZE)
645         );
646     }
647     else {
648         /* don't do anything. might give out a warning if(data[0] != 0) */
649         return 0;
650     }
651     return 0;
652 }
653
654 jm_vector(jm_voidp)* fmi2_xml_get_variables_original_order(fmi2_xml_model_description_t* md) {
655         return md->variablesOrigOrder;
656 }
657
658 jm_vector(jm_named_ptr)* fmi2_xml_get_variables_alphabetical_order(fmi2_xml_model_description_t* md){
659         return &md->variablesByName;
660 }
661
662 jm_vector(jm_voidp)* fmi2_xml_get_variables_vr_order(fmi2_xml_model_description_t* md) {
663         return md->variablesByVR;
664 }
665
666
667 fmi2_xml_variable_t* fmi2_xml_get_variable_by_name(fmi2_xml_model_description_t* md, const char* name) {
668         jm_named_ptr key, *found;
669     key.name = name;
670     found = jm_vector_bsearch(jm_named_ptr)(&md->variablesByName, &key, jm_compare_named);
671         if(!found) return 0;
672         return found->ptr;
673 }
674
675
676 fmi2_xml_variable_t* fmi2_xml_get_variable_by_vr(fmi2_xml_model_description_t* md, fmi2_base_type_enu_t baseType, fmi2_value_reference_t vr) {
677     fmi2_xml_variable_t key;
678     fmi2_xml_variable_t *pkey = &key;
679         fmi2_xml_variable_type_base_t keyType;
680         fmi2_xml_variable_t *v = 0;
681     void ** found;
682         if(!md->variablesByVR) return 0;
683         keyType.structKind = fmi2_xml_type_struct_enu_props;
684         keyType.baseType = baseType;
685         key.typeBase = &keyType;
686         key.vr = vr;
687     key.aliasKind = fmi2_variable_is_not_alias;
688
689     found = jm_vector_bsearch(jm_voidp)(md->variablesByVR,(void**)&pkey, fmi2_xml_compare_vr);
690     if(!found) return 0;
691     v = (fmi2_xml_variable_t*)(*found);
692     return v;
693 }
694
695