source: azure_iot_hub_f767zi/trunk/azure_iot_sdk/serializer/src/schema.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 138.0 KB
Line 
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#include <stdlib.h>
5#include "azure_c_shared_utility/gballoc.h"
6
7#include "schema.h"
8#include "azure_c_shared_utility/crt_abstractions.h"
9#include "azure_c_shared_utility/xlogging.h"
10#include "azure_c_shared_utility/vector.h"
11
12
13MU_DEFINE_ENUM_STRINGS_WITHOUT_INVALID(SCHEMA_RESULT, SCHEMA_RESULT_VALUES);
14
15typedef struct SCHEMA_PROPERTY_HANDLE_DATA_TAG
16{
17 const char* PropertyName;
18 const char* PropertyType;
19} SCHEMA_PROPERTY_HANDLE_DATA;
20
21typedef struct SCHEMA_REPORTED_PROPERTY_HANDLE_DATA_TAG
22{
23 const char* reportedPropertyName;
24 const char* reportedPropertyType;
25} SCHEMA_REPORTED_PROPERTY_HANDLE_DATA;
26
27typedef struct SCHEMA_DESIRED_PROPERTY_HANDLE_DATA_TAG
28{
29 pfOnDesiredProperty onDesiredProperty;
30 pfDesiredPropertyInitialize desiredPropertInitialize;
31 pfDesiredPropertyDeinitialize desiredPropertDeinitialize;
32 const char* desiredPropertyName;
33 const char* desiredPropertyType;
34 pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE;
35 size_t offset;
36} SCHEMA_DESIRED_PROPERTY_HANDLE_DATA;
37
38typedef struct SCHEMA_ACTION_ARGUMENT_HANDLE_DATA_TAG
39{
40 const char* Name;
41 const char* Type;
42} SCHEMA_ACTION_ARGUMENT_HANDLE_DATA;
43
44typedef struct SCHEMA_METHOD_ARGUMENT_HANDLE_DATA_TAG
45{
46 char* Name;
47 char* Type;
48} SCHEMA_METHOD_ARGUMENT_HANDLE_DATA;
49
50typedef struct SCHEMA_ACTION_HANDLE_DATA_TAG
51{
52 const char* ActionName;
53 size_t ArgumentCount;
54 SCHEMA_ACTION_ARGUMENT_HANDLE* ArgumentHandles;
55} SCHEMA_ACTION_HANDLE_DATA;
56
57typedef struct SCHEMA_METHOD_HANDLE_DATA_TAG
58{
59 char* methodName;
60 VECTOR_HANDLE methodArguments; /*holds SCHEMA_METHOD_ARGUMENT_HANDLE*/
61} SCHEMA_METHOD_HANDLE_DATA;
62
63typedef struct MODEL_IN_MODEL_TAG
64{
65 pfOnDesiredProperty onDesiredProperty; /*is NULL if not specified or if the model in model is not WITH_DESIRED_PROPERTY*/
66 size_t offset; /*offset of the model in model (offsetof)*/
67 const char* propertyName;
68 SCHEMA_MODEL_TYPE_HANDLE modelHandle;
69} MODEL_IN_MODEL;
70
71typedef struct SCHEMA_MODEL_TYPE_HANDLE_DATA_TAG
72{
73 VECTOR_HANDLE methods; /*holds SCHEMA_METHOD_HANDLE*/
74 VECTOR_HANDLE desiredProperties; /*holds SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*/
75 const char* Name;
76 SCHEMA_HANDLE SchemaHandle;
77 SCHEMA_PROPERTY_HANDLE* Properties;
78 size_t PropertyCount;
79 VECTOR_HANDLE reportedProperties; /*holds SCHEMA_REPORTED_PROPERTY_HANDLE*/
80 SCHEMA_ACTION_HANDLE* Actions;
81 size_t ActionCount;
82 VECTOR_HANDLE models;
83 size_t DeviceCount;
84} SCHEMA_MODEL_TYPE_HANDLE_DATA;
85
86typedef struct SCHEMA_STRUCT_TYPE_HANDLE_DATA_TAG
87{
88 const char* Name;
89 SCHEMA_PROPERTY_HANDLE* Properties;
90 size_t PropertyCount;
91} SCHEMA_STRUCT_TYPE_HANDLE_DATA;
92
93typedef struct SCHEMA_HANDLE_DATA_TAG
94{
95 void* metadata;
96 const char* Namespace;
97 SCHEMA_MODEL_TYPE_HANDLE* ModelTypes;
98 size_t ModelTypeCount;
99 SCHEMA_STRUCT_TYPE_HANDLE* StructTypes;
100 size_t StructTypeCount;
101} SCHEMA_HANDLE_DATA;
102
103static VECTOR_HANDLE g_schemas = NULL;
104
105static void DestroyProperty(SCHEMA_PROPERTY_HANDLE propertyHandle)
106{
107 SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
108 free((void*)propertyType->PropertyName);
109 free((void*)propertyType->PropertyType);
110 free(propertyType);
111}
112
113static void DestroyActionArgument(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
114{
115 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
116 if (actionArgument != NULL)
117 {
118 free((void*)actionArgument->Name);
119 free((void*)actionArgument->Type);
120 free(actionArgument);
121 }
122}
123
124static void DestroyMethodArgument(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
125{
126 free(methodArgumentHandle->Name);
127 free(methodArgumentHandle->Type);
128 free(methodArgumentHandle);
129}
130
131static void DestroyAction(SCHEMA_ACTION_HANDLE actionHandle)
132{
133 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
134 if (action != NULL)
135 {
136 size_t j;
137
138 for (j = 0; j < action->ArgumentCount; j++)
139 {
140 DestroyActionArgument(action->ArgumentHandles[j]);
141 }
142 free(action->ArgumentHandles);
143
144 free((void*)action->ActionName);
145 free(action);
146 }
147}
148
149static void DestroyMethod(SCHEMA_METHOD_HANDLE methodHandle)
150{
151 size_t nArguments = VECTOR_size(methodHandle->methodArguments);
152
153 for (size_t j = 0; j < nArguments; j++)
154 {
155 SCHEMA_METHOD_ARGUMENT_HANDLE* methodArgumentHandle = VECTOR_element(methodHandle->methodArguments, j);
156 DestroyMethodArgument(*methodArgumentHandle);
157 }
158 free(methodHandle->methodName);
159 VECTOR_destroy(methodHandle->methodArguments);
160 free(methodHandle);
161}
162
163static void DestroyMethods(SCHEMA_MODEL_TYPE_HANDLE modelHandle)
164{
165 size_t nMethods = VECTOR_size(modelHandle->methods);
166
167 for (size_t j = 0; j < nMethods; j++)
168 {
169 SCHEMA_METHOD_HANDLE* methodHandle = VECTOR_element(modelHandle->methods, j);
170 DestroyMethod(*methodHandle);
171 }
172 VECTOR_destroy(modelHandle->methods);
173}
174
175
176static void DestroyStruct(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle)
177{
178 size_t i;
179 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
180 if (structType != NULL)
181 {
182 for (i = 0; i < structType->PropertyCount; i++)
183 {
184 DestroyProperty(structType->Properties[i]);
185 }
186 free(structType->Properties);
187
188 free((void*)structType->Name);
189
190 free(structType);
191 }
192}
193
194static void DestroyModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
195{
196 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
197 size_t i, nReportedProperties;
198
199 free((void*)modelType->Name);
200 modelType->Name = NULL;
201
202 for (i = 0; i < modelType->PropertyCount; i++)
203 {
204 DestroyProperty(modelType->Properties[i]);
205 }
206
207 free(modelType->Properties);
208
209 for (i = 0; i < modelType->ActionCount; i++)
210 {
211 DestroyAction(modelType->Actions[i]);
212 }
213
214 DestroyMethods(modelType);
215
216 /*destroy the vector holding the added models. This does not destroy the said models, however, their names shall be*/
217 for (i = 0; i < VECTOR_size(modelType->models); i++)
218 {
219 MODEL_IN_MODEL* temp = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
220 free((void*)temp->propertyName);
221 }
222
223 nReportedProperties = VECTOR_size(modelType->reportedProperties);
224 for (i = 0;i < nReportedProperties;i++)
225 {
226 SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->reportedProperties, i);
227 free((void*)reportedProperty->reportedPropertyName);
228 free((void*)reportedProperty->reportedPropertyType);
229 free(reportedProperty);
230 }
231 VECTOR_destroy(modelType->reportedProperties);
232
233 size_t nDesiredProperties = VECTOR_size(modelType->desiredProperties);
234 for (i = 0;i < nDesiredProperties;i++)
235 {
236 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->desiredProperties, i);
237 free((void*)desiredProperty->desiredPropertyName);
238 free((void*)desiredProperty->desiredPropertyType);
239 free(desiredProperty);
240 }
241 VECTOR_destroy(modelType->desiredProperties);
242
243 VECTOR_clear(modelType->models);
244 VECTOR_destroy(modelType->models);
245
246 free(modelType->Actions);
247 free(modelType);
248}
249
250static SCHEMA_RESULT AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType, const char* name, const char* type)
251{
252 SCHEMA_RESULT result;
253
254 /* Codes_SRS_SCHEMA_99_013:[If any of the arguments is NULL, Schema_AddModelProperty shall return SCHEMA_INVALID_ARG.] */
255 if ((modelType == NULL) ||
256 (name == NULL) ||
257 (type == NULL))
258 {
259 result = SCHEMA_INVALID_ARG;
260 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
261 }
262 else
263 {
264 size_t i;
265
266 /* Codes_SRS_SCHEMA_99_015:[The property name shall be unique per model, if the same property name is added twice to a model, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */
267 for (i = 0; i < modelType->PropertyCount; i++)
268 {
269 SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
270 if (strcmp(property->PropertyName, name) == 0)
271 {
272 break;
273 }
274 }
275
276 if (i < modelType->PropertyCount)
277 {
278 result = SCHEMA_DUPLICATE_ELEMENT;
279 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
280 }
281 else
282 {
283 SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (modelType->PropertyCount + 1));
284 if (newProperties == NULL)
285 {
286 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
287 result = SCHEMA_ERROR;
288 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
289 }
290 else
291 {
292 SCHEMA_PROPERTY_HANDLE_DATA* newProperty;
293
294 modelType->Properties = newProperties;
295 if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL)
296 {
297 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
298 result = SCHEMA_ERROR;
299 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
300 }
301 else
302 {
303 if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, name) != 0)
304 {
305 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
306 free(newProperty);
307 result = SCHEMA_ERROR;
308 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
309 }
310 else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, type) != 0)
311 {
312 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
313 free((void*)newProperty->PropertyName);
314 free(newProperty);
315 result = SCHEMA_ERROR;
316 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
317 }
318 else
319 {
320 modelType->Properties[modelType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty;
321 modelType->PropertyCount++;
322
323 /* Codes_SRS_SCHEMA_99_012:[On success, Schema_AddModelProperty shall return SCHEMA_OK.] */
324 result = SCHEMA_OK;
325 }
326 }
327
328 /* If possible, reduce the memory of over allocation */
329 if (result != SCHEMA_OK)
330 {
331 if (modelType->PropertyCount > 0)
332 {
333 SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * modelType->PropertyCount);
334 if (oldProperties == NULL)
335 {
336 result = SCHEMA_ERROR;
337 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
338 }
339 else
340 {
341 modelType->Properties = oldProperties;
342 }
343 }
344 else
345 {
346 modelType->Properties = NULL;
347 }
348 }
349 }
350 }
351 }
352
353 return result;
354}
355
356static bool SchemaHandlesMatch(const SCHEMA_HANDLE* handle, const SCHEMA_HANDLE* otherHandle)
357{
358 return (*handle == *otherHandle);
359}
360
361static bool SchemaNamespacesMatch(const SCHEMA_HANDLE* handle, const char* schemaNamespace)
362{
363 const SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)*handle;
364 return (strcmp(schema->Namespace, schemaNamespace) == 0);
365}
366
367/* Codes_SRS_SCHEMA_99_001:[Schema_Create shall initialize a schema with a given namespace.] */
368SCHEMA_HANDLE Schema_Create(const char* schemaNamespace, void* metadata)
369{
370 SCHEMA_HANDLE_DATA* result;
371 /*Codes_SRS_SCHEMA_02_090: [ If metadata is NULL then Schema_Create shall fail and return NULL. ]*/
372 /* Codes_SRS_SCHEMA_99_004:[If schemaNamespace is NULL, Schema_Create shall fail.] */
373 if (
374 (schemaNamespace == NULL)||
375 (metadata == NULL)
376 )
377 {
378 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
379 LogError("invalid arg const char* schemaNamespace=%p, void* metadata=%p",schemaNamespace, metadata);
380 result = NULL;
381 }
382 else
383 {
384 if (g_schemas == NULL && (g_schemas = VECTOR_create(sizeof(SCHEMA_HANDLE_DATA*) ) ) == NULL)
385 {
386 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
387 result = NULL;
388 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
389 }
390 else if ((result = (SCHEMA_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_HANDLE_DATA))) == NULL)
391 {
392 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
393 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
394 }
395 else if (mallocAndStrcpy_s((char**)&result->Namespace, schemaNamespace) != 0)
396 {
397 /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
398 free(result);
399 result = NULL;
400 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
401 }
402 else if (VECTOR_push_back(g_schemas, &result, 1) != 0)
403 {
404 free((void*)result->Namespace);
405 free(result);
406 result = NULL;
407 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
408 }
409 else
410 {
411 /* Codes_SRS_SCHEMA_99_002:[On success a non-NULL handle to the newly created schema shall be returned.] */
412 result->ModelTypes = NULL;
413 result->ModelTypeCount = 0;
414 result->StructTypes = NULL;
415 result->StructTypeCount = 0;
416 result->metadata = metadata;
417 }
418 }
419
420 return (SCHEMA_HANDLE)result;
421}
422
423size_t Schema_GetSchemaCount(void)
424{
425 /* Codes_SRS_SCHEMA_99_153: [Schema_GetSchemaCount shall return the number of "active" schemas (all schemas created with Schema_Create
426 in the current process, for which Schema_Destroy has not been called).] */
427 return VECTOR_size(g_schemas);
428}
429
430SCHEMA_HANDLE Schema_GetSchemaByNamespace(const char* schemaNamespace)
431{
432 /* Codes_SRS_SCHEMA_99_151: [If no active schema matches the schemaNamespace argument, Schema_GetSchemaByNamespace shall return NULL.] */
433 SCHEMA_HANDLE result = NULL;
434
435 /* Codes_SRS_SCHEMA_99_150: [If the schemaNamespace argument is NULL, Schema_GetSchemaByNamespace shall return NULL.] */
436 if (schemaNamespace != NULL)
437 {
438 SCHEMA_HANDLE* handle = (g_schemas==NULL)?NULL:(SCHEMA_HANDLE*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaNamespacesMatch, schemaNamespace);
439 if (handle != NULL)
440 {
441 /* Codes_SRS_SCHEMA_99_148: [Schema_GetSchemaByNamespace shall search all active schemas and return the schema with the
442 namespace given by the schemaNamespace argument.] */
443 result = *handle;
444 }
445 }
446
447 return result;
448}
449
450const char* Schema_GetSchemaNamespace(SCHEMA_HANDLE schemaHandle)
451{
452 const char* result;
453
454 /* Codes_SRS_SCHEMA_99_130: [If the schemaHandle argument is NULL, Schema_GetSchemaNamespace shall return NULL.] */
455 if (schemaHandle == NULL)
456 {
457 result = NULL;
458 }
459 else
460 {
461 /* Codes_SRS_SCHEMA_99_129: [Schema_GetSchemaNamespace shall return the namespace for the schema identified by schemaHandle.] */
462 result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->Namespace;
463 }
464
465 return result;
466}
467
468void Schema_Destroy(SCHEMA_HANDLE schemaHandle)
469{
470 /* Codes_SRS_SCHEMA_99_006:[If the schemaHandle is NULL, Schema_Destroy shall do nothing.] */
471 if (schemaHandle != NULL)
472 {
473 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
474 size_t i;
475
476 /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */
477 for (i = 0; i < schema->ModelTypeCount; i++)
478 {
479 DestroyModel(schema->ModelTypes[i]);
480 }
481
482 free(schema->ModelTypes);
483
484 /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */
485 for (i = 0; i < schema->StructTypeCount; i++)
486 {
487 DestroyStruct(schema->StructTypes[i]);
488 }
489
490 free(schema->StructTypes);
491 free((void*)schema->Namespace);
492 free(schema);
493
494 schema = (SCHEMA_HANDLE_DATA*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHandlesMatch, &schemaHandle);
495 if (schema != NULL)
496 {
497 VECTOR_erase(g_schemas, schema, 1);
498 }
499 // If the g_schema is empty then destroy it
500 if (VECTOR_size(g_schemas) == 0)
501 {
502 VECTOR_destroy(g_schemas);
503 g_schemas = NULL;
504 }
505 }
506}
507
508SCHEMA_RESULT Schema_DestroyIfUnused(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
509{
510 SCHEMA_RESULT result;
511
512 /* Codes_SRS_SCHEMA_07_189: [If modelHandle variable is NULL Schema_DestroyIfUnused shall do nothing.] */
513 if (modelTypeHandle != NULL)
514 {
515 SCHEMA_HANDLE schemaHandle = Schema_GetSchemaForModelType(modelTypeHandle);
516 if (schemaHandle == NULL)
517 {
518 result = SCHEMA_ERROR;
519 }
520 else
521 {
522 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
523 size_t nIndex;
524
525 /* Codes_SRS_SCHEMA_07_190: [Schema_DestroyIfUnused shall iterate through the ModuleTypes objects and if all the DeviceCount variables 0 then it will delete the schemaHandle.] */
526 for (nIndex = 0; nIndex < schema->ModelTypeCount; nIndex++)
527 {
528 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[nIndex];
529 if (modelType->DeviceCount > 0)
530 break;
531 }
532 /* Codes_SRS_SCHEMA_07_191: [If 1 or more DeviceCount variables are > 0 then Schema_DestroyIfUnused shall do nothing.] */
533 if (nIndex == schema->ModelTypeCount)
534 {
535 Schema_Destroy(schemaHandle);
536 result = SCHEMA_OK;
537 }
538 else
539 {
540 result = SCHEMA_MODEL_IN_USE;
541 }
542 }
543 }
544 else
545 {
546 result = SCHEMA_INVALID_ARG;
547 }
548 return result;
549}
550
551SCHEMA_RESULT Schema_AddDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
552{
553 SCHEMA_RESULT result;
554 if (modelTypeHandle == NULL)
555 {
556 /* Codes_SRS_SCHEMA_07_187: [Schema_AddDeviceRef shall return SCHEMA_INVALID_ARG if modelTypeHandle is NULL.] */
557 result = SCHEMA_INVALID_ARG;
558 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
559 }
560 else
561 {
562 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
563 /* Codes_SRS_SCHEMA_07_188: [If the modelTypeHandle is nonNULL, Schema_AddDeviceRef shall increment the SCHEMA_MODEL_TYPE_HANDLE_DATA DeviceCount variable.] */
564 model->DeviceCount++;
565 result = SCHEMA_OK;
566 }
567 return result;
568}
569
570SCHEMA_RESULT Schema_ReleaseDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
571{
572 SCHEMA_RESULT result;
573 /* Codes_SRS_SCHEMA_07_184: [Schema_DeviceRelease shall do nothing if the supplied modelHandle is NULL.] */
574 if (modelTypeHandle == NULL)
575 {
576 result = SCHEMA_INVALID_ARG;
577 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
578 }
579 else
580 {
581 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
582 if (model->DeviceCount > 0)
583 {
584 /* Codes_SRS_SCHEMA_07_186: [On a nonNULL SCHEMA_MODEL_TYPE_HANDLE if the DeviceCount variable is > 0 then the variable will be decremented.] */
585 model->DeviceCount--;
586 result = SCHEMA_OK;
587 }
588 else
589 {
590result = SCHEMA_DEVICE_COUNT_ZERO;
591LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
592 }
593 }
594 return result;
595}
596
597/* Codes_SRS_SCHEMA_99_007:[Schema_CreateModelType shall create a new model type and return a handle to it.] */
598SCHEMA_MODEL_TYPE_HANDLE Schema_CreateModelType(SCHEMA_HANDLE schemaHandle, const char* modelName)
599{
600 SCHEMA_MODEL_TYPE_HANDLE result;
601
602 /* Codes_SRS_SCHEMA_99_010:[If any of the arguments is NULL, Schema_CreateModelType shall fail.] */
603 if ((schemaHandle == NULL) ||
604 (modelName == NULL))
605 {
606 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
607 result = NULL;
608 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
609 }
610 else
611 {
612 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
613
614 /* Codes_SRS_SCHEMA_99_100: [Schema_CreateModelType shall return SCHEMA_DUPLICATE_ELEMENT if modelName already exists.] */
615 size_t i;
616 for (i = 0; i < schema->ModelTypeCount; i++)
617 {
618 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)(schema->ModelTypes[i]);
619 if (strcmp(model->Name, modelName) == 0)
620 {
621 break;
622 }
623 }
624
625 if (i < schema->ModelTypeCount)
626 {
627 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
628 result = NULL;
629 LogError("%s Model Name already exists", modelName);
630 }
631
632 else
633 {
634 SCHEMA_MODEL_TYPE_HANDLE* newModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * (schema->ModelTypeCount + 1));
635 if (newModelTypes == NULL)
636 {
637 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
638 result = NULL;
639 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
640 }
641 else
642 {
643 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType;
644 schema->ModelTypes = newModelTypes;
645
646 if ((modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_MODEL_TYPE_HANDLE_DATA))) == NULL)
647 {
648
649 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
650 result = NULL;
651 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
652 }
653 else if (mallocAndStrcpy_s((char**)&modelType->Name, modelName) != 0)
654 {
655 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
656 result = NULL;
657 free(modelType);
658 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
659 }
660 else
661 {
662 modelType->models = VECTOR_create(sizeof(MODEL_IN_MODEL));
663 if (modelType->models == NULL)
664 {
665 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
666 LogError("unable to VECTOR_create");
667 free((void*)modelType->Name);
668 free((void*)modelType);
669 result = NULL;
670 }
671 else
672 {
673 if ((modelType->reportedProperties = VECTOR_create(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE))) == NULL)
674 {
675 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
676 LogError("failed to VECTOR_create (reported properties)");
677 VECTOR_destroy(modelType->models);
678 free((void*)modelType->Name);
679 free((void*)modelType);
680 result = NULL;
681
682 }
683 else
684 {
685 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
686 if ((modelType->desiredProperties = VECTOR_create(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE))) == NULL)
687 {
688 LogError("failure in VECTOR_create (desired properties)");
689 VECTOR_destroy(modelType->reportedProperties);
690 VECTOR_destroy(modelType->models);
691 free((void*)modelType->Name);
692 free((void*)modelType);
693 result = NULL;
694 }
695 else
696 {
697 if ((modelType->methods = VECTOR_create(sizeof(SCHEMA_METHOD_HANDLE))) == NULL)
698 {
699 LogError("failure in VECTOR_create (desired properties)");
700 VECTOR_destroy(modelType->desiredProperties);
701 VECTOR_destroy(modelType->reportedProperties);
702 VECTOR_destroy(modelType->models);
703 free((void*)modelType->Name);
704 free((void*)modelType);
705 result = NULL;
706 }
707 else
708 {
709 modelType->PropertyCount = 0;
710 modelType->Properties = NULL;
711 modelType->ActionCount = 0;
712 modelType->Actions = NULL;
713 modelType->SchemaHandle = schemaHandle;
714 modelType->DeviceCount = 0;
715
716 schema->ModelTypes[schema->ModelTypeCount] = modelType;
717 schema->ModelTypeCount++;
718 /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */
719 result = (SCHEMA_MODEL_TYPE_HANDLE)modelType;
720 }
721 }
722 }
723 }
724 }
725
726 /* If possible, reduce the memory of over allocation */
727 if ((result == NULL) &&(schema->ModelTypeCount>0))
728 {
729 SCHEMA_MODEL_TYPE_HANDLE* oldModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * schema->ModelTypeCount);
730 if (oldModelTypes == NULL)
731 {
732 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
733 }
734 else
735 {
736 schema->ModelTypes = oldModelTypes;
737 }
738 }
739 }
740 }
741 }
742
743 return result;
744}
745
746SCHEMA_HANDLE Schema_GetSchemaForModelType(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
747{
748 SCHEMA_HANDLE result;
749
750 if (modelTypeHandle == NULL)
751 {
752 /* Codes_SRS_SCHEMA_99_132: [If the modelTypeHandle argument is NULL, Schema_GetSchemaForModelType shall return NULL.] */
753 result = NULL;
754 }
755 else
756 {
757 /* Codes_SRS_SCHEMA_99_131: [Schema_GetSchemaForModelType returns the schema handle for a given model type.] */
758 result = ((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle)->SchemaHandle;
759 }
760
761 return result;
762}
763
764/* Codes_SRS_SCHEMA_99_011:[Schema_AddModelProperty shall add one property to the model type identified by modelTypeHandle.] */
765SCHEMA_RESULT Schema_AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, const char* propertyType)
766{
767 return AddModelProperty((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle, propertyName, propertyType);
768}
769
770static bool reportedPropertyExists(const void* element, const void* value)
771{
772 SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA**)element;
773 return (strcmp(reportedProperty->reportedPropertyName, value) == 0);
774}
775
776SCHEMA_RESULT Schema_AddModelReportedProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName, const char* reportedPropertyType)
777{
778 SCHEMA_RESULT result;
779 /*Codes_SRS_SCHEMA_02_001: [ If modelTypeHandle is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
780 /*Codes_SRS_SCHEMA_02_002: [ If reportedPropertyName is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
781 /*Codes_SRS_SCHEMA_02_003: [ If reportedPropertyType is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
782 if (
783 (modelTypeHandle == NULL) ||
784 (reportedPropertyName == NULL) ||
785 (reportedPropertyType == NULL)
786 )
787 {
788 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p, const char* reportedPropertyType=%p", modelTypeHandle, reportedPropertyName, reportedPropertyType);
789 result = SCHEMA_INVALID_ARG;
790 }
791 else
792 {
793 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
794 /*Codes_SRS_SCHEMA_02_004: [ If reportedPropertyName has already been added then Schema_AddModelReportedProperty shall fail and return SCHEMA_PROPERTY_ELEMENT_EXISTS. ]*/
795 if (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName) != NULL)
796 {
797 LogError("unable to add reportedProperty %s because it already exists", reportedPropertyName);
798 result = SCHEMA_DUPLICATE_ELEMENT;
799 }
800 else
801 {
802 /*Codes_SRS_SCHEMA_02_005: [ Schema_AddModelReportedProperty shall record reportedPropertyName and reportedPropertyType. ]*/
803 SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = (SCHEMA_REPORTED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA));
804 if (reportedProperty == NULL)
805 {
806 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
807 LogError("unable to malloc");
808 result = SCHEMA_ERROR;
809 }
810 else
811 {
812 if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyName, reportedPropertyName) != 0)
813 {
814 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
815 LogError("unable to mallocAndStrcpy_s");
816 free(reportedProperty);
817 result = SCHEMA_ERROR;
818 }
819 else
820 {
821 if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyType, reportedPropertyType) != 0)
822 {
823 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
824 LogError("unable to mallocAndStrcpy_s");
825 free((void*)reportedProperty->reportedPropertyName);
826 free(reportedProperty);
827 result = SCHEMA_ERROR;
828 }
829 else
830 {
831 if (VECTOR_push_back(modelType->reportedProperties, &reportedProperty, 1) != 0)
832 {
833 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
834 LogError("unable to VECTOR_push_back");
835 free((void*)reportedProperty->reportedPropertyType);
836 free((void*)reportedProperty->reportedPropertyName);
837 free(reportedProperty);
838 result = SCHEMA_ERROR;
839 }
840 else
841 {
842 /*Codes_SRS_SCHEMA_02_007: [ Otherwise Schema_AddModelReportedProperty shall succeed and return SCHEMA_OK. ]*/
843 result = SCHEMA_OK;
844 }
845 }
846 }
847 }
848 }
849 }
850 return result;
851}
852
853SCHEMA_ACTION_HANDLE Schema_CreateModelAction(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName)
854{
855 SCHEMA_ACTION_HANDLE result;
856
857 /* Codes_SRS_SCHEMA_99_104: [If any of the modelTypeHandle or actionName arguments is NULL, Schema_CreateModelAction shall return NULL.] */
858 if ((modelTypeHandle == NULL) ||
859 (actionName == NULL))
860 {
861 result = NULL;
862 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
863 }
864 else
865 {
866 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
867 size_t i;
868
869 /* Codes_SRS_SCHEMA_99_105: [The action name shall be unique per model, if the same action name is added twice to a model, Schema_CreateModelAction shall return NULL.] */
870 for (i = 0; i < modelType->ActionCount; i++)
871 {
872 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i];
873 if (strcmp(action->ActionName, actionName) == 0)
874 {
875 break;
876 }
877 }
878
879 if (i < modelType->ActionCount)
880 {
881 result = NULL;
882 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT));
883 }
884 else
885 {
886 /* Codes_SRS_SCHEMA_99_102: [Schema_CreateModelAction shall add one action to the model type identified by modelTypeHandle.] */
887 SCHEMA_ACTION_HANDLE* newActions = (SCHEMA_ACTION_HANDLE*)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * (modelType->ActionCount + 1));
888 if (newActions == NULL)
889 {
890 /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
891 result = NULL;
892 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
893 }
894 else
895 {
896 SCHEMA_ACTION_HANDLE_DATA* newAction;
897 modelType->Actions = newActions;
898
899 /* Codes_SRS_SCHEMA_99_103: [On success, Schema_CreateModelAction shall return a none-NULL SCHEMA_ACTION_HANDLE to the newly created action.] */
900 if ((newAction = (SCHEMA_ACTION_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_ACTION_HANDLE_DATA))) == NULL)
901 {
902 /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
903 result = NULL;
904 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
905 }
906 else
907 {
908 if (mallocAndStrcpy_s((char**)&newAction->ActionName, actionName) != 0)
909 {
910 /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
911 free(newAction);
912 result = NULL;
913 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
914 }
915 else
916 {
917 newAction->ArgumentCount = 0;
918 newAction->ArgumentHandles = NULL;
919
920 modelType->Actions[modelType->ActionCount] = newAction;
921 modelType->ActionCount++;
922 result = (SCHEMA_ACTION_HANDLE)(newAction);
923 }
924
925 /* If possible, reduce the memory of over allocation */
926 if (result == NULL)
927 {
928 if (modelType->ActionCount > 0)
929 {
930 SCHEMA_ACTION_HANDLE *oldActions = (SCHEMA_ACTION_HANDLE *)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * modelType->ActionCount);
931 if (oldActions == NULL)
932 {
933 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
934 }
935 else
936 {
937 modelType->Actions = oldActions;
938 }
939 }
940 else
941 {
942 modelType->Actions = NULL;
943 }
944 }
945 }
946 }
947 }
948 }
949 return result;
950}
951
952
953static bool methodExists(const void* element, const void* value)
954{
955 const SCHEMA_METHOD_HANDLE* method = (const SCHEMA_METHOD_HANDLE*)element;
956 return (strcmp((*method)->methodName, value) == 0);
957}
958
959
960SCHEMA_METHOD_HANDLE Schema_CreateModelMethod(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName)
961{
962 SCHEMA_METHOD_HANDLE result;
963
964 /*Codes_SRS_SCHEMA_02_096: [ If modelTypeHandle is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/
965 /*Codes_SRS_SCHEMA_02_097: [ If methodName is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/
966 if ((modelTypeHandle == NULL) ||
967 (methodName == NULL))
968 {
969 result = NULL;
970 LogError("invalid argument: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName);
971 }
972 else
973 {
974 /*Codes_SRS_SCHEMA_02_103: [ If methodName already exists, then Schema_CreateModelMethod shall fail and return NULL. ]*/
975 if (VECTOR_find_if(modelTypeHandle->methods, methodExists, methodName) != NULL)
976 {
977 LogError("method %s already exists", methodName);
978 result = NULL;
979 }
980 else
981 {
982 /*Codes_SRS_SCHEMA_02_098: [ Schema_CreateModelMethod shall allocate the space for the method. ]*/
983 result = malloc(sizeof(SCHEMA_METHOD_HANDLE_DATA));
984 if (result == NULL)
985 {
986 LogError("failed to malloc");
987 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
988 /*return as is*/
989 }
990 else
991 {
992 /*Codes_SRS_SCHEMA_02_099: [ Schema_CreateModelMethod shall create a VECTOR that will hold the method's arguments. ]*/
993 result->methodArguments = VECTOR_create(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE));
994 if (result->methodArguments == NULL)
995 {
996 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
997 LogError("failure in VECTOR_create");
998 free(result);
999 result = NULL;
1000 }
1001 else
1002 {
1003 /*Codes_SRS_SCHEMA_02_100: [ Schema_CreateModelMethod shall clone methodName ]*/
1004 if (mallocAndStrcpy_s(&result->methodName, methodName) != 0)
1005 {
1006 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
1007 LogError("failure in mallocAndStrcpy_s");
1008 VECTOR_destroy(result->methodArguments);
1009 free(result);
1010 result = NULL;
1011 }
1012 else
1013 {
1014 /*Codes_SRS_SCHEMA_02_101: [ Schema_CreateModelMethod shall add the new created method to the model's list of methods. ]*/
1015 if (VECTOR_push_back(modelTypeHandle->methods, &result, 1) != 0)
1016 {
1017 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
1018 LogError("failure in VECTOR_push_back");
1019 free(result->methodName);
1020 VECTOR_destroy(result->methodArguments);
1021 free(result);
1022 result = NULL;
1023 }
1024 else
1025 {
1026 /*Codes_SRS_SCHEMA_02_104: [ Otherwise, Schema_CreateModelMethod shall succeed and return a non-NULL SCHEMA_METHOD_HANDLE. ]*/
1027 /*return as is*/
1028 }
1029 }
1030 }
1031 }
1032 }
1033 }
1034 return result;
1035}
1036
1037
1038SCHEMA_RESULT Schema_AddModelActionArgument(SCHEMA_ACTION_HANDLE actionHandle, const char* argumentName, const char* argumentType)
1039{
1040 SCHEMA_RESULT result;
1041
1042 /* Codes_SRS_SCHEMA_99_109: [If any of the arguments is NULL, Schema_AddModelActionArgument shall return SCHEMA_INVALID_ARG.] */
1043 if ((actionHandle == NULL) ||
1044 (argumentName == NULL) ||
1045 (argumentType == NULL))
1046 {
1047 result = SCHEMA_INVALID_ARG;
1048 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1049 }
1050 else
1051 {
1052 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
1053
1054 /* Codes_SRS_SCHEMA_99_110: [The argument name shall be unique per action, if the same name is added twice to an action, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */
1055 /* Codes_SRS_SCHEMA_99_111: [Schema_AddModelActionArgument shall accept arguments with different names of the same type.] */
1056 size_t i;
1057 for (i = 0; i < action->ArgumentCount; i++)
1058 {
1059 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)action->ArgumentHandles[i];
1060 if (strcmp((actionArgument->Name), argumentName) == 0)
1061 {
1062 break;
1063 }
1064 }
1065
1066 if (i < action->ArgumentCount)
1067 {
1068 result = SCHEMA_DUPLICATE_ELEMENT;
1069 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1070 }
1071 else
1072 {
1073 /* Codes_SRS_SCHEMA_99_107: [Schema_AddModelActionArgument shall add one argument name & type to an action identified by actionHandle.] */
1074 SCHEMA_ACTION_ARGUMENT_HANDLE* newArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE*)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * (action->ArgumentCount + 1));
1075 if (newArguments == NULL)
1076 {
1077 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
1078 result = SCHEMA_ERROR;
1079 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1080 }
1081 else
1082 {
1083 action->ArgumentHandles = newArguments;
1084
1085 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* newActionArgument;
1086
1087 action->ArgumentHandles = newArguments;
1088 if ((newActionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE_DATA))) == NULL)
1089 {
1090 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
1091 result = SCHEMA_ERROR;
1092 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1093 }
1094 else
1095 {
1096 if (mallocAndStrcpy_s((char**)&newActionArgument->Name, argumentName) != 0)
1097 {
1098 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
1099 free(newActionArgument);
1100 result = SCHEMA_ERROR;
1101 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1102 }
1103 else if (mallocAndStrcpy_s((char**)&newActionArgument->Type, argumentType) != 0)
1104 {
1105 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
1106 free((void*)newActionArgument->Name);
1107 free(newActionArgument);
1108 result = SCHEMA_ERROR;
1109 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1110 }
1111 else
1112 {
1113 /* Codes_SRS_SCHEMA_99_119: [Schema_AddModelActionArgument shall preserve the order of the action arguments according to the order in which they were added, starting with index 0 for the first added argument.] */
1114 action->ArgumentHandles[action->ArgumentCount] = newActionArgument;
1115 action->ArgumentCount++;
1116
1117 /* Codes_SRS_SCHEMA_99_108: [On success, Schema_AddModelActionArgunent shall return SCHEMA_OK.] */
1118 result = SCHEMA_OK;
1119 }
1120 }
1121
1122 /* If possible, reduce the memory of over allocation */
1123 if (result == SCHEMA_ERROR)
1124 {
1125 if (action->ArgumentCount > 0)
1126 {
1127 SCHEMA_ACTION_ARGUMENT_HANDLE *oldArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE *)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * action->ArgumentCount);
1128 if (oldArguments == NULL)
1129 {
1130 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
1131 }
1132 else
1133 {
1134 action->ArgumentHandles = oldArguments;
1135 }
1136 }
1137 else
1138 {
1139 action->ArgumentHandles = NULL;
1140 }
1141 }
1142 }
1143 }
1144 }
1145 return result;
1146}
1147
1148static bool methodFindArgumentByBame(const void* element, const void* value)
1149{
1150 /*element is a pointer to SCHEMA_METHOD_ARGUMENT_HANDLE*/
1151 const SCHEMA_METHOD_ARGUMENT_HANDLE* decodedElement = (const SCHEMA_METHOD_ARGUMENT_HANDLE*)element;
1152 const char* name = (const char*)value;
1153 return (strcmp((*decodedElement)->Name, name) == 0);
1154}
1155
1156SCHEMA_RESULT Schema_AddModelMethodArgument(SCHEMA_METHOD_HANDLE methodHandle, const char* argumentName, const char* argumentType)
1157{
1158 SCHEMA_RESULT result;
1159 /*Codes_SRS_SCHEMA_02_105: [ If methodHandle is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
1160 /*Codes_SRS_SCHEMA_02_106: [ If argumentName is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
1161 /*Codes_SRS_SCHEMA_02_107: [ If argumentType is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
1162 if ((methodHandle == NULL) ||
1163 (argumentName == NULL) ||
1164 (argumentType == NULL))
1165 {
1166 result = SCHEMA_INVALID_ARG;
1167 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1168 }
1169 else
1170 {
1171 /*Codes_SRS_SCHEMA_02_108: [ If argumentName already exists in the list of arguments then then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
1172 if (VECTOR_find_if(methodHandle->methodArguments, methodFindArgumentByBame, argumentName) != NULL)
1173 {
1174 LogError("an argument with name %s already exists", argumentName);
1175 result = SCHEMA_INVALID_ARG;
1176 }
1177 else
1178 {
1179 /*Codes_SRS_SCHEMA_02_109: [ Schema_AddModelMethodArgument shall allocate memory for the new argument. ]*/
1180 SCHEMA_METHOD_ARGUMENT_HANDLE_DATA* argument = malloc(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE_DATA));
1181 if (argument == NULL)
1182 {
1183 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
1184 LogError("failure to malloc");
1185 result = SCHEMA_ERROR;
1186 }
1187 else
1188 {
1189 /*Codes_SRS_SCHEMA_02_110: [ Schema_AddModelMethodArgument shall clone methodHandle. ]*/
1190 if (mallocAndStrcpy_s(&argument->Name, argumentName) != 0)
1191 {
1192 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
1193 LogError("failure in mallocAndStrcpy_s");
1194 free(argument);
1195 result = SCHEMA_ERROR;
1196 }
1197 else
1198 {
1199 /*Codes_SRS_SCHEMA_02_111: [ Schema_AddModelMethodArgument shall clone argumentType. ]*/
1200 if (mallocAndStrcpy_s(&argument->Type, argumentType) != 0)
1201 {
1202 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
1203 LogError("failure in mallocAndStrcpy_s");
1204 free(argument->Name);
1205 free(argument);
1206 result = SCHEMA_ERROR;
1207 }
1208 else
1209 {
1210 /*Codes_SRS_SCHEMA_02_112: [ Schema_AddModelMethodArgument shall add the created argument to the method's list of arguments. ]*/
1211 if (VECTOR_push_back(methodHandle->methodArguments, &argument, 1) != 0)
1212 {
1213 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
1214 LogError("failure in VECTOR_push_back");
1215 free(argument->Name);
1216 free(argument->Type);
1217 free(argument);
1218 result = SCHEMA_ERROR;
1219 }
1220 else
1221 {
1222 /*Codes_SRS_SCHEMA_02_114: [ Otherwise, Schema_AddModelMethodArgument shall succeed and return SCHEMA_OK. ]*/
1223 result = SCHEMA_OK;
1224 }
1225 }
1226 }
1227 }
1228 }
1229 }
1230 return result;
1231}
1232
1233SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
1234{
1235 SCHEMA_PROPERTY_HANDLE result;
1236
1237 /* Codes_SRS_SCHEMA_99_038:[Schema_GetModelPropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
1238 if ((modelTypeHandle == NULL) ||
1239 (propertyName == NULL))
1240 {
1241 result = NULL;
1242 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1243 }
1244 else
1245 {
1246 size_t i;
1247 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1248
1249 /* Codes_SRS_SCHEMA_99_036:[Schema_GetModelPropertyByName shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the model type identified by modelTypeHandle and matching the propertyName argument value.] */
1250 for (i = 0; i < modelType->PropertyCount; i++)
1251 {
1252 SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
1253 if (strcmp(modelProperty->PropertyName, propertyName) == 0)
1254 {
1255 break;
1256 }
1257 }
1258
1259 if (i == modelType->PropertyCount)
1260 {
1261 /* Codes_SRS_SCHEMA_99_038:[Schema_GetModelPropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
1262 result = NULL;
1263 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
1264 }
1265 else
1266 {
1267 result = (SCHEMA_PROPERTY_HANDLE)(modelType->Properties[i]);
1268 }
1269 }
1270
1271 return result;
1272}
1273
1274SCHEMA_RESULT Schema_GetModelPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* propertyCount)
1275{
1276 SCHEMA_RESULT result;
1277
1278 /* Codes_SRS_SCHEMA_99_092: [Schema_GetModelPropertyCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
1279 if ((modelTypeHandle == NULL) ||
1280 (propertyCount == NULL))
1281 {
1282 result = SCHEMA_INVALID_ARG;
1283 }
1284 else
1285 {
1286 /* Codes_SRS_SCHEMA_99_089: [Schema_GetModelPropertyCount shall provide the number of properties defined in the model type identified by modelTypeHandle.] */
1287 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1288
1289 /* Codes_SRS_SCHEMA_99_090: [The count shall be provided via the out argument propertyCount.]*/
1290 *propertyCount = modelType->PropertyCount;
1291
1292 /* Codes_SRS_SCHEMA_99_091: [On success, Schema_GetModelPropertyCount shall return SCHEMA_OK.] */
1293 result = SCHEMA_OK;
1294 }
1295
1296 return result;
1297}
1298
1299SCHEMA_RESULT Schema_GetModelReportedPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* reportedPropertyCount)
1300{
1301 SCHEMA_RESULT result;
1302 /*Codes_SRS_SCHEMA_02_008: [ If parameter modelTypeHandle is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
1303 /*Codes_SRS_SCHEMA_02_009: [ If parameter reportedPropertyCount is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
1304 if (
1305 (modelTypeHandle == NULL)||
1306 (reportedPropertyCount==NULL)
1307 )
1308 {
1309 LogError("SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* reportedPropertyCount=%p", modelTypeHandle, reportedPropertyCount);
1310 result = SCHEMA_INVALID_ARG;
1311 }
1312 else
1313 {
1314 /*Codes_SRS_SCHEMA_02_010: [ Schema_GetModelReportedPropertyCount shall provide in reportedPropertyCount the number of reported properties and return SCHEMA_OK. ]*/
1315 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1316 *reportedPropertyCount = VECTOR_size(modelType->reportedProperties);
1317 result = SCHEMA_OK;
1318 }
1319 return result;
1320}
1321
1322SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName)
1323{
1324 SCHEMA_REPORTED_PROPERTY_HANDLE result;
1325 /*Codes_SRS_SCHEMA_02_011: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
1326 /*Codes_SRS_SCHEMA_02_012: [ If argument reportedPropertyName is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
1327 if(
1328 (modelTypeHandle == NULL) ||
1329 (reportedPropertyName == NULL)
1330 )
1331 {
1332 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p", modelTypeHandle, reportedPropertyName);
1333 result = NULL;
1334 }
1335 else
1336 {
1337 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1338 /*Codes_SRS_SCHEMA_02_013: [ If reported property by the name reportedPropertyName exists then Schema_GetModelReportedPropertyByName shall succeed and return a non-NULL value. ]*/
1339 /*Codes_SRS_SCHEMA_02_014: [ Otherwise Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
1340 if((result = VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName))==NULL)
1341 {
1342 LogError("a reported property with name \"%s\" does not exist", reportedPropertyName);
1343 }
1344 else
1345 {
1346 /*return as is*/
1347 }
1348 }
1349 return result;
1350}
1351
1352SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
1353{
1354 SCHEMA_REPORTED_PROPERTY_HANDLE result;
1355 /*Codes_SRS_SCHEMA_02_015: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/
1356 if (modelTypeHandle == NULL)
1357 {
1358 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%lu", modelTypeHandle, (unsigned long)index);
1359 result = NULL;
1360 }
1361 else
1362 {
1363 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1364
1365 /*Codes_SRS_SCHEMA_02_016: [ If a reported property with index equal to index exists then Schema_GetModelReportedPropertyByIndex shall succeed and return the non-NULL handle of that REPORTED_PROPERTY. ]*/
1366 /*Codes_SRS_SCHEMA_02_017: [ Otherwise Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/
1367 if ((result = VECTOR_element(modelType->reportedProperties, index)) == NULL)
1368 {
1369 LogError("index %lu is invalid", (unsigned long)index);
1370 }
1371 else
1372 {
1373 /*return as is*/
1374 }
1375 }
1376 return result;
1377}
1378
1379SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
1380{
1381 SCHEMA_PROPERTY_HANDLE result;
1382 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1383
1384 /* Codes_SRS_SCHEMA_99_094: [Schema_GetModelProperty shall return NULL if the index specified is outside the valid range or if modelTypeHandle argument is NULL.] */
1385 if ((modelTypeHandle == NULL) ||
1386 (index >= modelType->PropertyCount))
1387 {
1388 result = NULL;
1389 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1390 }
1391 else
1392 {
1393 /* Tests_SRS_SCHEMA_99_093: [Schema_GetModelProperty shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the model type identified by modelTypeHandle and matching the index number provided by the index argument.] */
1394 /* Codes_SRS_SCHEMA_99_097: [index is zero based, and the order in which actions were added shall be the index in which they will be retrieved.] */
1395 result = modelType->Properties[index];
1396 }
1397
1398 return result;
1399}
1400
1401SCHEMA_ACTION_HANDLE Schema_GetModelActionByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName)
1402{
1403 SCHEMA_ACTION_HANDLE result;
1404
1405 /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */
1406 if ((modelTypeHandle == NULL) ||
1407 (actionName == NULL))
1408 {
1409 result = NULL;
1410 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1411 }
1412 else
1413 {
1414 size_t i;
1415 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1416
1417 /* Codes_SRS_SCHEMA_99_040:[Schema_GetModelActionByName shall return a non-NULL SCHEMA_ACTION_HANDLE corresponding to the model type identified by modelTypeHandle and matching the actionName argument value.] */
1418 for (i = 0; i < modelType->ActionCount; i++)
1419 {
1420 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i];
1421 if (strcmp(modelAction->ActionName, actionName) == 0)
1422 {
1423 break;
1424 }
1425 }
1426
1427 if (i == modelType->ActionCount)
1428 {
1429 /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */
1430 result = NULL;
1431 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
1432 }
1433 else
1434 {
1435 result = modelType->Actions[i];
1436 }
1437 }
1438
1439 return result;
1440}
1441
1442static bool matchModelMethod(const void* element, const void* value)
1443{
1444 /*element is a pointer to SCHEMA_METHOD_HANDLE_DATA*/
1445 const SCHEMA_METHOD_HANDLE* decodedElement = (const SCHEMA_METHOD_HANDLE* )element;
1446 const char* name = (const char*)value;
1447 return (strcmp((*decodedElement)->methodName, name) == 0);
1448}
1449
1450SCHEMA_METHOD_HANDLE Schema_GetModelMethodByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName)
1451{
1452 SCHEMA_METHOD_HANDLE result;
1453
1454 /*Codes_SRS_SCHEMA_02_115: [ If modelTypeHandle is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/
1455 /*Codes_SRS_SCHEMA_02_116: [ If methodName is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/
1456 if ((modelTypeHandle == NULL) ||
1457 (methodName == NULL))
1458 {
1459 result = NULL;
1460 LogError("invalid arguments SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName);
1461 }
1462 else
1463 {
1464 /*Codes_SRS_SCHEMA_02_117: [ If a method with the name methodName exists then Schema_GetModelMethodByName shall succeed and returns its handle. ]*/
1465 SCHEMA_METHOD_HANDLE* found = VECTOR_find_if(modelTypeHandle->methods, matchModelMethod, methodName);
1466 if (found == NULL)
1467 {
1468 /*Codes_SRS_SCHEMA_02_118: [ Otherwise, Schema_GetModelMethodByName shall fail and return NULL. ]*/
1469 LogError("no such method by name = %s", methodName);
1470 result = NULL;
1471 }
1472 else
1473 {
1474 result = *found;
1475 }
1476 }
1477
1478 return result;
1479}
1480
1481SCHEMA_RESULT Schema_GetModelActionCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* actionCount)
1482{
1483 SCHEMA_RESULT result;
1484
1485 /* Codes_SRS_SCHEMA_99_045:[If any of the modelTypeHandle or actionCount arguments is NULL, Schema_GetModelActionCount shall return SCHEMA_INVALID_ARG.] */
1486 if ((modelTypeHandle == NULL) ||
1487 (actionCount == NULL))
1488 {
1489 result = SCHEMA_INVALID_ARG;
1490 LogError("(result=%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1491 }
1492 else
1493 {
1494 /* Codes_SRS_SCHEMA_99_042:[Schema_GetModelActionCount shall provide the total number of actions defined in a model type identified by the modelTypeHandle.] */
1495 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1496
1497 /* Codes_SRS_SCHEMA_99_043:[The count shall be provided via the out argument actionCount.] */
1498 *actionCount = modelType->ActionCount;
1499
1500 /* Codes_SRS_SCHEMA_99_044:[On success, Schema_GetModelActionCount shall return SCHEMA_OK.] */
1501 result = SCHEMA_OK;
1502 }
1503
1504 return result;
1505}
1506
1507SCHEMA_ACTION_HANDLE Schema_GetModelActionByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
1508{
1509 SCHEMA_ACTION_HANDLE result;
1510 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
1511
1512 /* Codes_SRS_SCHEMA_99_048:[Schema_GetModelAction shall return NULL if the index specified is outside the valid range or if modelTypeHandle argument is NULL.] */
1513 if ((modelType == NULL) ||
1514 (index >= modelType->ActionCount))
1515 {
1516 result = NULL;
1517 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1518 }
1519 else
1520 {
1521 /* Codes_SRS_SCHEMA_99_047:[Schema_GetModelAction shall return a non-NULL SCHEMA_ACTION_HANDLE corresponding to the model type identified by modelTypeHandle and matching the index number provided by the index argument.] */
1522 /* Codes_SRS_SCHEMA_99_096: [index is zero based and the order in which actions were added shall be the index in which they will be retrieved.] */
1523 result = modelType->Actions[index];
1524 }
1525
1526 return result;
1527}
1528
1529const char* Schema_GetModelActionName(SCHEMA_ACTION_HANDLE actionHandle)
1530{
1531 const char* result;
1532
1533 /* Codes_SRS_SCHEMA_99_050:[If the actionHandle is NULL, Schema_GetModelActionName shall return NULL.] */
1534 if (actionHandle == NULL)
1535 {
1536 result = NULL;
1537 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1538 }
1539 else
1540 {
1541 SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
1542 /* Codes_SRS_SCHEMA_99_049:[Schema_GetModelActionName shall return the action name for a given action handle.] */
1543 result = action->ActionName;
1544 }
1545
1546 return result;
1547}
1548
1549SCHEMA_RESULT Schema_GetModelActionArgumentCount(SCHEMA_ACTION_HANDLE actionHandle, size_t* argumentCount)
1550{
1551 SCHEMA_RESULT result;
1552
1553 /* Codes_SRS_SCHEMA_99_054:[If any argument is NULL, Schema_GetModelActionArgumentCount shall return SCHEMA_INVALID_ARG.] */
1554 if ((actionHandle == NULL) ||
1555 (argumentCount == NULL))
1556 {
1557 result = SCHEMA_INVALID_ARG;
1558 LogError("(result=%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1559 }
1560 else
1561 {
1562 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
1563
1564 /* Codes_SRS_SCHEMA_99_051:[Schema_GetModelActionArgumentCount shall provide the number of arguments for a specific schema action identified by actionHandle.] */
1565 /* Codes_SRS_SCHEMA_99_052:[The argument count shall be provided via the out argument argumentCount.] */
1566 *argumentCount = modelAction->ArgumentCount;
1567
1568 /* Codes_SRS_SCHEMA_99_053:[On success, Schema_GetModelActionArgumentCount shall return SCHEMA_OK.] */
1569 result = SCHEMA_OK;
1570 }
1571
1572 return result;
1573}
1574
1575SCHEMA_RESULT Schema_GetModelMethodArgumentCount(SCHEMA_METHOD_HANDLE methodHandle, size_t* argumentCount)
1576{
1577 SCHEMA_RESULT result;
1578
1579 /*Codes_SRS_SCHEMA_02_119: [ If methodHandle is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/
1580 /*Codes_SRS_SCHEMA_02_120: [ If argumentCount is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/
1581 if ((methodHandle == NULL) ||
1582 (argumentCount == NULL))
1583 {
1584 result = SCHEMA_INVALID_ARG;
1585 LogError("(result=%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1586 }
1587 else
1588 {
1589 /*Codes_SRS_SCHEMA_02_121: [ Otherwise, Schema_GetModelMethodArgumentCount shall succeed, return in argumentCount the number of arguments for the method and return SCHEMA_OK. ]*/
1590 *argumentCount = VECTOR_size(methodHandle->methodArguments);
1591 result = SCHEMA_OK;
1592 }
1593
1594 return result;
1595}
1596
1597
1598SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByName(SCHEMA_ACTION_HANDLE actionHandle, const char* actionArgumentName)
1599{
1600 SCHEMA_ACTION_ARGUMENT_HANDLE result;
1601
1602 /* Codes_SRS_SCHEMA_99_118: [Schema_GetModelActionArgumentByName shall return NULL if unable to find a matching argument or if any of the arguments are NULL.] */
1603 if ((actionHandle == NULL) ||
1604 (actionArgumentName == NULL))
1605 {
1606 result = NULL;
1607 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1608 }
1609 else
1610 {
1611 /* Codes_SRS_SCHEMA_99_118: [Schema_GetModelActionArgumentByName shall return NULL if unable to find a matching argument or if any of the arguments are NULL.] */
1612 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
1613 size_t i;
1614
1615 for (i = 0; i < modelAction->ArgumentCount; i++)
1616 {
1617 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)modelAction->ArgumentHandles[i];
1618 if (strcmp(actionArgument->Name, actionArgumentName) == 0)
1619 {
1620 break;
1621 }
1622 }
1623
1624 if (i == modelAction->ArgumentCount)
1625 {
1626 /* Codes_SRS_SCHEMA_99_118: [Schema_GetModelActionArgumentByName shall return NULL if unable to find a matching argument or if any of the arguments are NULL.] */
1627 result = NULL;
1628 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
1629 }
1630 else
1631 {
1632 /* Codes_SRS_SCHEMA_99_117: [Schema_GetModelActionArgumentByName shall return a non-NULL handle corresponding to an action argument identified by the actionHandle and actionArgumentName.] */
1633 result = modelAction->ArgumentHandles[i];
1634 }
1635 }
1636
1637 return result;
1638}
1639
1640SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByIndex(SCHEMA_ACTION_HANDLE actionHandle, size_t argumentIndex)
1641{
1642 SCHEMA_ACTION_ARGUMENT_HANDLE result;
1643 SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
1644
1645 /* Codes_SRS_SCHEMA_99_056:[Schema_GetModelActionArgument shall return NULL if the index specified is outside the valid range or if the actionHandle argument is NULL.] */
1646 if ((actionHandle == NULL) ||
1647 (argumentIndex >= modelAction->ArgumentCount))
1648 {
1649 result = NULL;
1650 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1651 }
1652 else
1653 {
1654 /* Codes_SRS_SCHEMA_99_055:[Schema_GetModelActionArgument shall return a non-NULL SCHEMA_ACTION_ARGUMENT_HANDLE corresponding to the action type identified by actionHandle and matching the index number provided by the argumentIndex argument.] */
1655 result = modelAction->ArgumentHandles[argumentIndex];
1656 }
1657
1658 return result;
1659}
1660
1661SCHEMA_METHOD_ARGUMENT_HANDLE Schema_GetModelMethodArgumentByIndex(SCHEMA_METHOD_HANDLE methodHandle, size_t argumentIndex)
1662{
1663 SCHEMA_METHOD_ARGUMENT_HANDLE result;
1664
1665 /*Codes_SRS_SCHEMA_02_122: [ If methodHandle is NULL then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/
1666 if (methodHandle == NULL)
1667 {
1668 result = NULL;
1669 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1670 }
1671 else
1672 {
1673 /*Codes_SRS_SCHEMA_02_123: [ If argumentIndex does not exist then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/
1674 SCHEMA_METHOD_ARGUMENT_HANDLE *temp = VECTOR_element(methodHandle->methodArguments, argumentIndex);
1675 if (temp == NULL)
1676 {
1677 result = NULL;
1678 }
1679 else
1680 {
1681 /*Codes_SRS_SCHEMA_02_124: [ Otherwise, Schema_GetModelMethodArgumentByIndex shall succeed and return a non-NULL value. ]*/
1682 result = *temp;
1683 }
1684 }
1685
1686 return result;
1687}
1688
1689
1690const char* Schema_GetActionArgumentName(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
1691{
1692 const char* result;
1693 /* Codes_SRS_SCHEMA_99_114: [Schema_GetActionArgumentName shall return NULL if actionArgumentHandle is NULL.] */
1694 if (actionArgumentHandle == NULL)
1695 {
1696 result = NULL;
1697 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1698 }
1699 else
1700 {
1701 /* Codes_SRS_SCHEMA_99_113: [Schema_GetActionArgumentName shall return the argument name identified by the actionArgumentHandle.] */
1702 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
1703 result = actionArgument->Name;
1704 }
1705 return result;
1706}
1707
1708const char* Schema_GetMethodArgumentName(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
1709{
1710 const char* result;
1711 /*Codes_SRS_SCHEMA_02_125: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentName shall fail and return NULL. ]*/
1712 if (methodArgumentHandle == NULL)
1713 {
1714 result = NULL;
1715 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1716 }
1717 else
1718 {
1719 /*Codes_SRS_SCHEMA_02_126: [ Otherwise, Schema_GetMethodArgumentName shall succeed and return a non-NULL value. ]*/
1720 result = methodArgumentHandle->Name;
1721 }
1722 return result;
1723}
1724
1725
1726const char* Schema_GetActionArgumentType(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
1727{
1728 const char* result;
1729 /* Codes_SRS_SCHEMA_99_116: [Schema_GetActionArgumentType shall return NULL if actionArgumentHandle is NULL.] */
1730 if (actionArgumentHandle == NULL)
1731 {
1732 result = NULL;
1733 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1734 }
1735 else
1736 {
1737 /* Codes_SRS_SCHEMA_99_115: [Schema_GetActionArgumentType shall return the argument type identified by the actionArgumentHandle.] */
1738 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
1739 result = actionArgument->Type;
1740 }
1741 return result;
1742}
1743
1744const char* Schema_GetMethodArgumentType(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
1745{
1746 const char* result;
1747 /*Codes_SRS_SCHEMA_02_127: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentType shall fail and return NULL. ]*/
1748 if (methodArgumentHandle == NULL)
1749 {
1750 result = NULL;
1751 LogError("invalid argument SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle=%p", methodArgumentHandle);
1752 }
1753 else
1754 {
1755 /*Codes_SRS_SCHEMA_02_128: [ Otherwise, Schema_GetMethodArgumentType shall succeed and return a non-NULL value. ]*/
1756 result = methodArgumentHandle->Type;
1757 }
1758 return result;
1759}
1760
1761
1762SCHEMA_STRUCT_TYPE_HANDLE Schema_CreateStructType(SCHEMA_HANDLE schemaHandle, const char* typeName)
1763{
1764 SCHEMA_STRUCT_TYPE_HANDLE result;
1765 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
1766
1767 /* Codes_SRS_SCHEMA_99_060:[If any of the arguments is NULL, Schema_CreateStructType shall return NULL.] */
1768 if ((schema == NULL) ||
1769 (typeName == NULL))
1770 {
1771 result = NULL;
1772 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1773 }
1774 else
1775 {
1776 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType;
1777 size_t i;
1778
1779 /* Codes_SRS_SCHEMA_99_061:[If a struct type with the same name already exists, Schema_CreateStructType shall return NULL.] */
1780 for (i = 0; i < schema->StructTypeCount; i++)
1781 {
1782 structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i];
1783 if (strcmp(structType->Name, typeName) == 0)
1784 {
1785 break;
1786 }
1787 }
1788
1789 if (i < schema->StructTypeCount)
1790 {
1791 result = NULL;
1792 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT));
1793 }
1794 else
1795 {
1796 SCHEMA_STRUCT_TYPE_HANDLE* newStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE*)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * (schema->StructTypeCount + 1));
1797 if (newStructTypes == NULL)
1798 {
1799 /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
1800 result = NULL;
1801 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
1802 }
1803 else
1804 {
1805 schema->StructTypes = newStructTypes;
1806 if ((structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_STRUCT_TYPE_HANDLE_DATA))) == NULL)
1807 {
1808 /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
1809 result = NULL;
1810 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
1811 }
1812 else if (mallocAndStrcpy_s((char**)&structType->Name, typeName) != 0)
1813 {
1814 /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
1815 result = NULL;
1816 free(structType);
1817 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
1818 }
1819 else
1820 {
1821 /* Codes_SRS_SCHEMA_99_057:[Schema_CreateStructType shall create a new struct type and return a handle to it.] */
1822 schema->StructTypes[schema->StructTypeCount] = structType;
1823 schema->StructTypeCount++;
1824 structType->PropertyCount = 0;
1825 structType->Properties = NULL;
1826
1827 /* Codes_SRS_SCHEMA_99_058:[On success, a non-NULL handle shall be returned.] */
1828 result = (SCHEMA_STRUCT_TYPE_HANDLE)structType;
1829 }
1830
1831 /* If possible, reduce the memory of over allocation */
1832 if (result == NULL)
1833 {
1834 if (schema->StructTypeCount > 0)
1835 {
1836 SCHEMA_STRUCT_TYPE_HANDLE *oldStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE *)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * schema->StructTypeCount);
1837 if (oldStructTypes == NULL)
1838 {
1839 result = NULL;
1840 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
1841 }
1842 else
1843 {
1844 schema->StructTypes = oldStructTypes;
1845 }
1846 }
1847 else
1848 {
1849 schema->StructTypes = NULL;
1850 }
1851 }
1852 }
1853 }
1854 }
1855
1856 return result;
1857}
1858
1859const char* Schema_GetStructTypeName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle)
1860{
1861 const char* result;
1862
1863 /* Codes_SRS_SCHEMA_99_136: [If structTypeHandle is NULL, Schema_GetStructTypeName shall return NULL.] */
1864 if (structTypeHandle == NULL)
1865 {
1866 result = NULL;
1867 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1868 }
1869 else
1870 {
1871 /* Codes_SRS_SCHEMA_99_135: [Schema_GetStructTypeName shall return the name of a struct type identified by the structTypeHandle argument.] */
1872 result = ((SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle)->Name;
1873 }
1874
1875 return result;
1876}
1877
1878SCHEMA_RESULT Schema_GetStructTypeCount(SCHEMA_HANDLE schemaHandle, size_t* structTypeCount)
1879{
1880 SCHEMA_RESULT result;
1881
1882 /* Codes_SRS_SCHEMA_99_140: [Schema_GetStructTypeCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
1883 if ((schemaHandle == NULL) ||
1884 (structTypeCount == NULL))
1885 {
1886 result = SCHEMA_INVALID_ARG;
1887 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1888 }
1889 else
1890 {
1891 /* Codes_SRS_SCHEMA_99_137: [Schema_GetStructTypeCount shall provide the number of structs defined in the schema identified by schemaHandle.] */
1892 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
1893 /* Codes_SRS_SCHEMA_99_138: [The count shall be provided via the out argument structTypeCount.] */
1894 *structTypeCount = schema->StructTypeCount;
1895 /* Codes_SRS_SCHEMA_99_139: [On success, Schema_GetStructTypeCount shall return SCHEMA_OK.] */
1896 result = SCHEMA_OK;
1897 }
1898
1899 return result;
1900}
1901
1902SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByName(SCHEMA_HANDLE schemaHandle, const char* name)
1903{
1904 SCHEMA_STRUCT_TYPE_HANDLE result;
1905 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
1906
1907 /* Codes_SRS_SCHEMA_99_069:[Schema_GetStructTypeByName shall return NULL if unable to find a matching struct or if any of the arguments are NULL.] */
1908 if ((schemaHandle == NULL) ||
1909 (name == NULL))
1910 {
1911 result = NULL;
1912 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1913 }
1914 else
1915 {
1916 size_t i;
1917
1918 /* Codes_SRS_SCHEMA_99_068:[Schema_GetStructTypeByName shall return a non-NULL handle corresponding to the struct type identified by the structTypeName in the schemaHandle schema.] */
1919 for (i = 0; i < schema->StructTypeCount; i++)
1920 {
1921 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i];
1922 if (strcmp(structType->Name, name) == 0)
1923 {
1924 break;
1925 }
1926 }
1927
1928 if (i == schema->StructTypeCount)
1929 {
1930 /* Codes_SRS_SCHEMA_99_069:[Schema_GetStructTypeByName shall return NULL if unable to find a matching struct or if any of the arguments are NULL.] */
1931 result = NULL;
1932 LogError("(Error code:%s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
1933 }
1934 else
1935 {
1936 result = schema->StructTypes[i];
1937 }
1938 }
1939
1940 return result;
1941}
1942
1943SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByIndex(SCHEMA_HANDLE schemaHandle, size_t index)
1944{
1945 SCHEMA_STRUCT_TYPE_HANDLE result;
1946 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
1947
1948 /* Codes_SRS_SCHEMA_99_143: [Schema_GetStructTypeByIndex shall return NULL if the index specified is outside the valid range or if schemaHandle argument is NULL.] */
1949 /* Codes_SRS_SCHEMA_99_142: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
1950 if ((schemaHandle == NULL) ||
1951 (index >= schema->StructTypeCount))
1952 {
1953 result = NULL;
1954 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
1955 }
1956 else
1957 {
1958
1959 /* Codes_SRS_SCHEMA_99_141: [Schema_GetStructTypeByIndex shall return a non-NULL SCHEMA_STRUCT_TYPE_HANDLE corresponding to the struct type identified by schemaHandle and matching the index number provided by the index argument.] */
1960 /* Codes_SRS_SCHEMA_99_142: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
1961 result = schema->StructTypes[index];
1962 }
1963 return result;
1964}
1965
1966SCHEMA_RESULT Schema_AddStructTypeProperty(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName, const char* propertyType)
1967{
1968 SCHEMA_RESULT result;
1969
1970 /* Codes_SRS_SCHEMA_99_072:[If any of the arguments is NULL, Schema_AddStructTypeProperty shall return SCHEMA_INVALID_ARG.] */
1971 if ((structTypeHandle == NULL) ||
1972 (propertyName == NULL) ||
1973 (propertyType == NULL))
1974 {
1975 result = SCHEMA_INVALID_ARG;
1976 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1977 }
1978 else
1979 {
1980 size_t i;
1981 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
1982
1983 /* Codes_SRS_SCHEMA_99_074:[The property name shall be unique per struct type, if the same property name is added twice to a struct type, SCHEMA_DUPLICATE_ELEMENT shall be returned.] */
1984 for (i = 0; i < structType->PropertyCount; i++)
1985 {
1986 SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i];
1987 if (strcmp(property->PropertyName, propertyName) == 0)
1988 {
1989 break;
1990 }
1991 }
1992
1993 if (i < structType->PropertyCount)
1994 {
1995 result = SCHEMA_DUPLICATE_ELEMENT;
1996 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
1997 }
1998 else
1999 {
2000 SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (structType->PropertyCount + 1));
2001 if (newProperties == NULL)
2002 {
2003 result = SCHEMA_ERROR;
2004 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2005 }
2006 else
2007 {
2008 SCHEMA_PROPERTY_HANDLE_DATA* newProperty;
2009
2010 structType->Properties = newProperties;
2011 if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL)
2012 {
2013 result = SCHEMA_ERROR;
2014 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2015 }
2016 else
2017 {
2018 if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, propertyName) != 0)
2019 {
2020 free(newProperty);
2021 result = SCHEMA_ERROR;
2022 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2023 }
2024 else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, propertyType) != 0)
2025 {
2026 free((void*)newProperty->PropertyName);
2027 free(newProperty);
2028 result = SCHEMA_ERROR;
2029 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2030 }
2031 else
2032 {
2033 /* Codes_SRS_SCHEMA_99_070:[Schema_AddStructTypeProperty shall add one property to the struct type identified by structTypeHandle.] */
2034 structType->Properties[structType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty;
2035 structType->PropertyCount++;
2036
2037 /* Codes_SRS_SCHEMA_99_071:[On success, Schema_AddStructTypeProperty shall return SCHEMA_OK.] */
2038 result = SCHEMA_OK;
2039 }
2040 }
2041
2042 /* If possible, reduce the memory of over allocation */
2043 if (result != SCHEMA_OK)
2044 {
2045 if (structType->PropertyCount > 0)
2046 {
2047 SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * structType->PropertyCount);
2048 if (oldProperties == NULL)
2049 {
2050 result = SCHEMA_ERROR;
2051 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2052 }
2053 else
2054 {
2055 structType->Properties = oldProperties;
2056 }
2057 }
2058 else
2059 {
2060 structType->Properties = NULL;
2061 }
2062 }
2063 }
2064 }
2065 }
2066
2067 return result;
2068}
2069
2070SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName)
2071{
2072 SCHEMA_PROPERTY_HANDLE result;
2073
2074 /* Codes_SRS_SCHEMA_99_076:[Schema_GetStructTypePropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
2075 if ((structTypeHandle == NULL) ||
2076 (propertyName == NULL))
2077 {
2078 result = NULL;
2079 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
2080 }
2081 else
2082 {
2083 size_t i;
2084 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
2085
2086 for (i = 0; i < structType->PropertyCount; i++)
2087 {
2088 SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i];
2089 if (strcmp(modelProperty->PropertyName, propertyName) == 0)
2090 {
2091 break;
2092 }
2093 }
2094
2095 /* Codes_SRS_SCHEMA_99_076:[Schema_GetStructTypePropertyByName shall return NULL if unable to find a matching property or if any of the arguments are NULL.] */
2096 if (i == structType->PropertyCount)
2097 {
2098 result = NULL;
2099 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
2100 }
2101 /* Codes_SRS_SCHEMA_99_075:[Schema_GetStructTypePropertyByName shall return a non-NULL handle corresponding to a property identified by the structTypeHandle and propertyName.] */
2102 else
2103 {
2104 result = structType->Properties[i];
2105 }
2106 }
2107
2108 return result;
2109}
2110
2111SCHEMA_RESULT Schema_GetStructTypePropertyCount(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t* propertyCount)
2112{
2113 SCHEMA_RESULT result;
2114
2115 /* Codes_SRS_SCHEMA_99_079: [Schema_GetStructTypePropertyCount shall return SCHEMA_INVALID_ARG if any of the structlTypeHandle or propertyCount arguments is NULL.] */
2116 if ((structTypeHandle == NULL) ||
2117 (propertyCount == NULL))
2118 {
2119 result = SCHEMA_INVALID_ARG;
2120 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2121 }
2122 else
2123 {
2124 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
2125
2126 /* Codes_SRS_SCHEMA_99_077: [Schema_GetStructTypePropertyCount shall provide the total number of properties defined in a struct type identified by structTypeHandle. The value is provided via the out argument propertyCount.] */
2127 /* Codes_SRS_SCHEMA_99_081: [The count shall be provided via the out argument propertyCount.] */
2128 *propertyCount = structType->PropertyCount;
2129
2130 /* Codes_SRS_SCHEMA_99_078: [On success, Schema_ GetStructTypePropertyCount shall return SCHEMA_OK.] */
2131 result = SCHEMA_OK;
2132 }
2133
2134 return result;
2135}
2136
2137SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByIndex(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t index)
2138{
2139 SCHEMA_PROPERTY_HANDLE result;
2140 SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
2141
2142 /* Codes_SRS_SCHEMA_99_083: [Schema_ GetStructTypeProperty shall return NULL if the index specified is outside the valid range, if structTypeHandle argument is NULL] */
2143 if ((structTypeHandle == NULL) ||
2144 (index >= structType->PropertyCount))
2145 {
2146 result = NULL;
2147 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
2148 }
2149 else
2150 {
2151 /* Codes_SRS_SCHEMA_99_082: [Schema_GetStructTypeProperty shall return a non-NULL SCHEMA_PROPERTY_HANDLE corresponding to the struct type identified by strutTypeHandle and matching the index number provided by the index argument.] */
2152 /* Codes_SRS_SCHEMA_99_098: [index is zero based and the order in which actions were added shall be the index in which they will be retrieved.] */
2153 result = structType->Properties[index];
2154 }
2155
2156 return result;
2157}
2158
2159const char* Schema_GetPropertyName(SCHEMA_PROPERTY_HANDLE propertyHandle)
2160{
2161 const char* result;
2162
2163 /* Codes_SRS_SCHEMA_99_086: [If propertyHandle is NULL, Schema_GetPropertyName shall return NULL.] */
2164 if (propertyHandle == NULL)
2165 {
2166 result = NULL;
2167 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
2168 }
2169 else
2170 {
2171 SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
2172
2173 /* Codes_SRS_SCHEMA_99_085: [Schema_GetPropertyName shall return the property name identified by the propertyHandle.] */
2174 result = propertyType->PropertyName;
2175 }
2176
2177 return result;
2178}
2179
2180const char* Schema_GetPropertyType(SCHEMA_PROPERTY_HANDLE propertyHandle)
2181{
2182 const char* result;
2183
2184 /* Codes_SRS_SCHEMA_99_088: [If propertyHandle is NULL, Schema_GetPropertyType shall return NULL.] */
2185 if (propertyHandle == NULL)
2186 {
2187 result = NULL;
2188 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
2189 }
2190 else
2191 {
2192 SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
2193
2194 /* Codes_SRS_SCHEMA_99_087: [Schema_GetPropertyType shall return the property type identified by the propertyHandle.] */
2195 result = modelProperty->PropertyType;
2196 }
2197
2198 return result;
2199}
2200
2201SCHEMA_RESULT Schema_GetModelCount(SCHEMA_HANDLE schemaHandle, size_t* modelCount)
2202{
2203 SCHEMA_RESULT result;
2204 /* Codes_SRS_SCHEMA_99_123: [Schema_GetModelCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
2205 if ((schemaHandle == NULL) ||
2206 (modelCount == NULL) )
2207 {
2208 result = SCHEMA_INVALID_ARG;
2209 LogError("(result = %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2210 }
2211 else
2212 {
2213 /* Codes_SRS_SCHEMA_99_120: [Schema_GetModelCount shall provide the number of models defined in the schema identified by schemaHandle.] */
2214 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
2215 /* Codes_SRS_SCHEMA_99_121: [The count shall be provided via the out argument modelCount.] */
2216 *modelCount = schema->ModelTypeCount;
2217 /* Codes_SRS_SCHEMA_99_122: [On success, Schema_GetModelCount shall return SCHEMA_OK.] */
2218 result = SCHEMA_OK;
2219 }
2220 return result;
2221}
2222
2223SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByName(SCHEMA_HANDLE schemaHandle, const char* modelName)
2224{
2225 SCHEMA_MODEL_TYPE_HANDLE result;
2226
2227 /* Codes_SRS_SCHEMA_99_125: [Schema_GetModelByName shall return NULL if unable to find a matching model, or if any of the arguments are NULL.] */
2228 if ((schemaHandle == NULL) ||
2229 (modelName == NULL))
2230 {
2231 result = NULL;
2232 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
2233 }
2234 else
2235 {
2236 /* Codes_SRS_SCHEMA_99_124: [Schema_GetModelByName shall return a non-NULL SCHEMA_MODEL_TYPE_HANDLE corresponding to the model identified by schemaHandle and matching the modelName argument value.] */
2237 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
2238 size_t i;
2239 for (i = 0; i < schema->ModelTypeCount; i++)
2240 {
2241 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[i];
2242 if (strcmp(modelName, modelType->Name)==0)
2243 {
2244 break;
2245 }
2246 }
2247 if (i == schema->ModelTypeCount)
2248 {
2249 /* Codes_SRS_SCHEMA_99_125: [Schema_GetModelByName shall return NULL if unable to find a matching model, or if any of the arguments are NULL.] */
2250 result = NULL;
2251 }
2252 else
2253 {
2254 result = schema->ModelTypes[i];
2255 }
2256 }
2257 return result;
2258}
2259
2260SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByIndex(SCHEMA_HANDLE schemaHandle, size_t index)
2261{
2262 SCHEMA_MODEL_TYPE_HANDLE result;
2263 SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
2264
2265 /* Codes_SRS_SCHEMA_99_128: [Schema_GetModelByIndex shall return NULL if the index specified is outside the valid range or if schemaHandle argument is NULL.] */
2266 /* Codes_SRS_SCHEMA_99_127: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
2267 if ((schemaHandle == NULL) ||
2268 (index >= schema->ModelTypeCount))
2269 {
2270 result = NULL;
2271 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
2272 }
2273 else
2274 {
2275
2276 /* Codes_SRS_SCHEMA_99_126: [Schema_GetModelByIndex shall return a non-NULL SCHEMA_MODEL_TYPE_HANDLE corresponding to the model identified by schemaHandle and matching the index number provided by the index argument.] */
2277 /* Codes_SRS_SCHEMA_99_127: [The index argument is zero based, and the order in which models were added shall be the index in which they will be retrieved.] */
2278 result = schema->ModelTypes[index];
2279 }
2280 return result;
2281}
2282
2283/*Codes_SRS_SCHEMA_99_160: [Schema_GetModelName shall return the name of the model identified by modelTypeHandle. If the name cannot be retrieved, then NULL shall be returned.]*/
2284const char* Schema_GetModelName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
2285{
2286 const char* result;
2287 if (modelTypeHandle == NULL)
2288 {
2289 result = NULL;
2290 }
2291 else
2292 {
2293 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2294 result = modelType->Name;
2295 }
2296 return result;
2297}
2298
2299/*Codes_SRS_SCHEMA_99_163: [Schema_AddModelModel shall insert an existing model, identified by the handle modelType, into the existing model identified by modelTypeHandle under a property having the name propertyName.]*/
2300SCHEMA_RESULT Schema_AddModelModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, SCHEMA_MODEL_TYPE_HANDLE modelType, size_t offset, pfOnDesiredProperty onDesiredProperty)
2301{
2302 SCHEMA_RESULT result;
2303 /*Codes_SRS_SCHEMA_99_165: [If any of the parameters is NULL then Schema_AddModelModel shall return SCHEMA_INVALID_ARG.]*/
2304 if (
2305 (modelTypeHandle == NULL) ||
2306 (propertyName == NULL) ||
2307 (modelType == NULL)
2308 )
2309 {
2310 result = SCHEMA_INVALID_ARG;
2311 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
2312 }
2313 else
2314 {
2315 SCHEMA_MODEL_TYPE_HANDLE_DATA* parentModel = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2316 MODEL_IN_MODEL temp;
2317 temp.modelHandle = modelType;
2318 temp.offset = offset;
2319 temp.onDesiredProperty = onDesiredProperty;
2320 if (mallocAndStrcpy_s((char**)&(temp.propertyName), propertyName) != 0)
2321 {
2322 result = SCHEMA_ERROR;
2323 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2324 }
2325 else if (VECTOR_push_back(parentModel->models, &temp, 1) != 0)
2326 {
2327 /*Codes_SRS_SCHEMA_99_174: [The function shall return SCHEMA_ERROR if any other error occurs.]*/
2328 free((void*)temp.propertyName);
2329 result = SCHEMA_ERROR;
2330 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2331 }
2332 else
2333 {
2334 /*Codes_SRS_SCHEMA_99_164: [If the function succeeds, then the return value shall be SCHEMA_OK.]*/
2335
2336 result = SCHEMA_OK;
2337 }
2338 }
2339 return result;
2340}
2341
2342
2343SCHEMA_RESULT Schema_GetModelModelCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* modelCount)
2344{
2345 SCHEMA_RESULT result;
2346 /*Codes_SRS_SCHEMA_99_169: [If any of the parameters is NULL, then the function shall return SCHEMA_INVALID_ARG.]*/
2347 if (
2348 (modelTypeHandle == NULL) ||
2349 (modelCount == NULL)
2350 )
2351 {
2352 result = SCHEMA_INVALID_ARG;
2353 LogError("(Error code: %s)", MU_ENUM_TO_STRING(SCHEMA_RESULT, result));
2354 }
2355 else
2356 {
2357 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2358 /*Codes_SRS_SCHEMA_99_167: [Schema_GetModelModelCount shall return in parameter modelCount the number of models inserted in the model identified by parameter modelTypeHandle.]*/
2359 *modelCount = VECTOR_size(model->models);
2360 /*SRS_SCHEMA_99_168: [If the function succeeds, it shall return SCHEMA_OK.]*/
2361 result = SCHEMA_OK;
2362 }
2363 return result;
2364}
2365
2366static bool matchModelName(const void* element, const void* value)
2367{
2368 MODEL_IN_MODEL* decodedElement = (MODEL_IN_MODEL*)element;
2369 const char* name = (const char*)value;
2370 return (strcmp(decodedElement->propertyName, name) == 0);
2371}
2372
2373SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
2374{
2375 SCHEMA_MODEL_TYPE_HANDLE result;
2376 if (
2377 (modelTypeHandle == NULL) ||
2378 (propertyName == NULL)
2379 )
2380 {
2381 /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
2382 result = NULL;
2383 LogError("error SCHEMA_INVALID_ARG");
2384 }
2385 else
2386 {
2387 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2388 /*Codes_SRS_SCHEMA_99_170: [Schema_GetModelModelByName shall return a handle to the model identified by the property with the name propertyName in the model identified by the handle modelTypeHandle.]*/
2389 /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
2390 void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
2391 if (temp == NULL)
2392 {
2393 LogError("specified propertyName not found (%s)", propertyName);
2394 result = NULL;
2395 }
2396 else
2397 {
2398 result = ((MODEL_IN_MODEL*)temp)->modelHandle;
2399 }
2400 }
2401 return result;
2402}
2403
2404size_t Schema_GetModelModelByName_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
2405{
2406 size_t result;
2407 /*Codes_SRS_SCHEMA_02_053: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
2408 /*Codes_SRS_SCHEMA_02_054: [ If propertyName is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
2409 if (
2410 (modelTypeHandle == NULL) ||
2411 (propertyName == NULL)
2412 )
2413 {
2414 /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
2415 result = 0;
2416 LogError("error SCHEMA_INVALID_ARG");
2417 }
2418 else
2419 {
2420 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2421 /*Codes_SRS_SCHEMA_02_056: [ If propertyName is not a model then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
2422 void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
2423 if (temp == NULL)
2424 {
2425 LogError("specified propertyName not found (%s)", propertyName);
2426 result = 0;
2427 }
2428 else
2429 {
2430 /*Codes_SRS_SCHEMA_02_055: [ Otherwise Schema_GetModelModelByName_Offset shall succeed and return the offset. ]*/
2431 result = ((MODEL_IN_MODEL*)temp)->offset;
2432 }
2433 }
2434 return result;
2435}
2436
2437pfOnDesiredProperty Schema_GetModelModelByName_OnDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
2438{
2439 pfOnDesiredProperty result;
2440 /*Codes_SRS_SCHEMA_02_086: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/
2441 /*Codes_SRS_SCHEMA_02_087: [ If propertyName is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/
2442 if (
2443 (modelTypeHandle == NULL) ||
2444 (propertyName == NULL)
2445 )
2446 {
2447 result = NULL;
2448 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* propertyName=%p",modelTypeHandle, propertyName);
2449 }
2450 else
2451 {
2452 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2453 void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
2454 if (temp == NULL)
2455 {
2456 LogError("specified propertyName not found (%s)", propertyName);
2457 result = NULL;
2458 }
2459 else
2460 {
2461 /*Codes_SRS_SCHEMA_02_089: [ Otherwise Schema_GetModelModelByName_OnDesiredProperty shall return the desired property callback. ]*/
2462 result = ((MODEL_IN_MODEL*)temp)->onDesiredProperty;
2463 }
2464 }
2465 return result;
2466
2467}
2468
2469size_t Schema_GetModelModelByIndex_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
2470{
2471 size_t result;
2472 /*Codes_SRS_SCHEMA_02_057: [ If modelTypeHandle is NULL then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/
2473 if (modelTypeHandle == NULL)
2474 {
2475 result = 0;
2476 LogError("error SCHEMA_INVALID_ARG");
2477 }
2478 else
2479 {
2480 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2481 /*Codes_SRS_SCHEMA_02_058: [ If index is not valid then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/
2482 void* temp = VECTOR_element(model->models, index);
2483 if (temp == 0)
2484 {
2485 LogError("specified index [out of bounds] (%lu)", (unsigned long)index);
2486 result = 0;
2487 }
2488 else
2489 {
2490 /*Codes_SRS_SCHEMA_02_059: [ Otherwise Schema_GetModelModelByIndex_Offset shall succeed and return the offset. ]*/
2491 result = ((MODEL_IN_MODEL*)temp)->offset;
2492 }
2493 }
2494 return result;
2495}
2496
2497SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
2498{
2499 SCHEMA_MODEL_TYPE_HANDLE result;
2500 if (modelTypeHandle == NULL)
2501 {
2502 /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/
2503 result = NULL;
2504 LogError("error SCHEMA_INVALID_ARG");
2505 }
2506 else
2507 {
2508 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2509 size_t nModelsInModel;
2510 /*Codes_SRS_SCHEMA_99_172: [ Schema_GetModelModelyByIndex shall return a handle to the "index"th model inserted in the model identified by the parameter modelTypeHandle.]*/
2511 /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/
2512 nModelsInModel = VECTOR_size(model->models);
2513 if (index < nModelsInModel)
2514 {
2515 result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->modelHandle;
2516 }
2517 else
2518 {
2519 LogError("attempted out of bounds access in array.");
2520 result = NULL; /*out of bounds array access*/
2521 }
2522 }
2523 return result;
2524}
2525
2526const char* Schema_GetModelModelPropertyNameByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
2527{
2528 const char* result;
2529 if (modelTypeHandle == NULL)
2530 {
2531 /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/
2532 result = NULL;
2533 }
2534 else
2535 {
2536 SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2537 size_t nModelsInModel;
2538 /*Codes_SRS_SCHEMA_99_175: [Schema_GetModelModelPropertyNameByIndex shall return the name of the property for the "index"th model in the model identified by modelTypeHandle parameter.]*/
2539 /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/
2540 nModelsInModel = VECTOR_size(model->models);
2541 if (index < nModelsInModel)
2542 {
2543 result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->propertyName;
2544 }
2545 else
2546 {
2547 LogError("attempted out of bounds access in array.");
2548 result = NULL; /*out of bounds array access*/
2549 }
2550 }
2551 return result;
2552}
2553
2554bool Schema_ModelPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyPath)
2555{
2556 bool result;
2557
2558 /* Codes_SRS_SCHEMA_99_180: [If any of the arguments are NULL, Schema_ModelPropertyByPathExists shall return false.] */
2559 if ((modelTypeHandle == NULL) ||
2560 (propertyPath == NULL))
2561 {
2562 LogError("error SCHEMA_INVALID_ARG");
2563 result = false;
2564 }
2565 else
2566 {
2567 const char* slashPos;
2568 result = false;
2569
2570 /* Codes_SRS_SCHEMA_99_182: [A single slash ('/') at the beginning of the path shall be ignored and the path shall still be valid.] */
2571 if (*propertyPath == '/')
2572 {
2573 propertyPath++;
2574 }
2575
2576 do
2577 {
2578 const char* endPos;
2579 size_t i;
2580 size_t modelCount;
2581 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2582
2583 /* Codes_SRS_SCHEMA_99_179: [The propertyPath shall be assumed to be in the format model1/model2/.../propertyName.] */
2584 slashPos = strchr(propertyPath, '/');
2585 endPos = slashPos;
2586 if (endPos == NULL)
2587 {
2588 endPos = &propertyPath[strlen(propertyPath)];
2589 }
2590
2591 /* get the child-model */
2592 modelCount = VECTOR_size(modelType->models);
2593 for (i = 0; i < modelCount; i++)
2594 {
2595 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
2596 if ((strncmp(childModel->propertyName, propertyPath, endPos - propertyPath) == 0) &&
2597 (strlen(childModel->propertyName) == (size_t)(endPos - propertyPath)))
2598 {
2599 /* found */
2600 modelTypeHandle = childModel->modelHandle;
2601 break;
2602 }
2603 }
2604
2605 if (i < modelCount)
2606 {
2607 /* model found, check if there is more in the path */
2608 if (slashPos == NULL)
2609 {
2610 /* this is the last one, so this is the thing we were looking for */
2611 result = true;
2612 break;
2613 }
2614 else
2615 {
2616 /* continue looking, there's more */
2617 propertyPath = slashPos + 1;
2618 }
2619 }
2620 else
2621 {
2622 /* no model found, let's see if this is a property */
2623 /* Codes_SRS_SCHEMA_99_178: [The argument propertyPath shall be used to find the leaf property.] */
2624 for (i = 0; i < modelType->PropertyCount; i++)
2625 {
2626 SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
2627 if ((strncmp(property->PropertyName, propertyPath, endPos - propertyPath) == 0) &&
2628 (strlen(property->PropertyName) == (size_t)(endPos - propertyPath)))
2629 {
2630 /* found property */
2631 /* Codes_SRS_SCHEMA_99_177: [Schema_ModelPropertyByPathExists shall return true if a leaf property exists in the model modelTypeHandle.] */
2632 result = true;
2633 break;
2634 }
2635 }
2636
2637 break;
2638 }
2639 } while (slashPos != NULL);
2640 }
2641
2642 return result;
2643}
2644
2645bool Schema_ModelReportedPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyPath)
2646{
2647 bool result;
2648
2649 /*Codes_SRS_SCHEMA_02_018: [ If argument modelTypeHandle is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
2650 /*Codes_SRS_SCHEMA_02_019: [ If argument reportedPropertyPath is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
2651 if ((modelTypeHandle == NULL) ||
2652 (reportedPropertyPath == NULL))
2653 {
2654 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyPath=%s", modelTypeHandle, reportedPropertyPath);
2655 result = false;
2656 }
2657 else
2658 {
2659 const char* slashPos;
2660
2661 /*Codes_SRS_SCHEMA_02_021: [ If the reported property cannot be found Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
2662 result = false;
2663
2664 /*Codes_SRS_SCHEMA_02_020: [ reportedPropertyPath shall be assumed to be in the format model1/model2/.../reportedPropertyName. ]*/
2665 if (*reportedPropertyPath == '/')
2666 {
2667 reportedPropertyPath++;
2668 }
2669
2670 do
2671 {
2672 const char* endPos;
2673 size_t i;
2674 size_t modelCount;
2675 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2676
2677 slashPos = strchr(reportedPropertyPath, '/');
2678 endPos = slashPos;
2679 if (endPos == NULL)
2680 {
2681 endPos = &reportedPropertyPath[strlen(reportedPropertyPath)];
2682 }
2683
2684 modelCount = VECTOR_size(modelType->models);
2685 for (i = 0; i < modelCount; i++)
2686 {
2687 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
2688 if ((strncmp(childModel->propertyName, reportedPropertyPath, endPos - reportedPropertyPath) == 0) &&
2689 (strlen(childModel->propertyName) == (size_t)(endPos - reportedPropertyPath)))
2690 {
2691 /* found */
2692 modelTypeHandle = childModel->modelHandle;
2693 break;
2694 }
2695 }
2696
2697 if (i < modelCount)
2698 {
2699 /* model found, check if there is more in the path */
2700 if (slashPos == NULL)
2701 {
2702 /*Codes_SRS_SCHEMA_02_022: [ If the path reportedPropertyPath points to a sub-model, Schema_ModelReportedPropertyByPathExists shall succeed and true. ]*/
2703 /* this is the last one, so this is the thing we were looking for */
2704 result = true;
2705 break;
2706 }
2707 else
2708 {
2709 /* continue looking, there's more */
2710 reportedPropertyPath = slashPos + 1;
2711 }
2712 }
2713 else
2714 {
2715 /* no model found, let's see if this is a property */
2716 result = (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyPath) != NULL);
2717 if (!result)
2718 {
2719 LogError("no such reported property \"%s\"", reportedPropertyPath);
2720 }
2721 break;
2722 }
2723 } while (slashPos != NULL);
2724 }
2725
2726 return result;
2727}
2728
2729static bool desiredPropertyExists(const void* element, const void* value)
2730{
2731 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA**)element;
2732 return (strcmp(desiredProperty->desiredPropertyName, value) == 0);
2733}
2734
2735SCHEMA_RESULT Schema_AddModelDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName, const char* desiredPropertyType, pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE, pfDesiredPropertyInitialize desiredPropertyInitialize, pfDesiredPropertyDeinitialize desiredPropertyDeinitialize, size_t offset, pfOnDesiredProperty onDesiredProperty)
2736{
2737 SCHEMA_RESULT result;
2738 /*Codes_SRS_SCHEMA_02_024: [ If modelTypeHandle is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
2739 /*Codes_SRS_SCHEMA_02_025: [ If desiredPropertyName is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
2740 /*Codes_SRS_SCHEMA_02_026: [ If desiredPropertyType is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
2741 /*Codes_SRS_SCHEMA_02_048: [ If desiredPropertyFromAGENT_DATA_TYPE is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
2742 /*Codes_SRS_SCHEMA_02_049: [ If desiredPropertyInitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
2743 /*Codes_SRS_SCHEMA_02_050: [ If desiredPropertyDeinitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
2744 if (
2745 (modelTypeHandle == NULL) ||
2746 (desiredPropertyName == NULL) ||
2747 (desiredPropertyType == NULL) ||
2748 (desiredPropertyFromAGENT_DATA_TYPE == NULL) ||
2749 (desiredPropertyInitialize == NULL) ||
2750 (desiredPropertyDeinitialize== NULL)
2751 )
2752 {
2753 LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p, const char* desiredPropertyType=%p, pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE=%p, pfDesiredPropertyInitialize desiredPropertyInitialize=%p, pfDesiredPropertyDeinitialize desiredPropertyDeinitialize=%p, size_t offset=%lu",
2754 modelTypeHandle, desiredPropertyName, desiredPropertyType, desiredPropertyFromAGENT_DATA_TYPE, desiredPropertyInitialize, desiredPropertyDeinitialize, (unsigned long)offset);
2755 result = SCHEMA_INVALID_ARG;
2756 }
2757 else
2758 {
2759 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2760 /*Codes_SRS_SCHEMA_02_027: [ Schema_AddModelDesiredProperty shall add the desired property given by the name desiredPropertyName and the type desiredPropertyType to the collection of existing desired properties. ]*/
2761 if (VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName) != NULL)
2762 {
2763 /*Codes_SRS_SCHEMA_02_047: [ If the desired property already exists, then Schema_AddModelDesiredProperty shall fail and return SCHEMA_DUPLICATE_ELEMENT. ]*/
2764 LogError("unable to Schema_AddModelDesiredProperty because a desired property with the same name (%s) already exists", desiredPropertyName);
2765 result = SCHEMA_DUPLICATE_ELEMENT;
2766 }
2767 else
2768 {
2769 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)calloc(1, sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA));
2770 if (desiredProperty == NULL)
2771 {
2772 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
2773 LogError("failure in malloc");
2774 result = SCHEMA_ERROR;
2775 }
2776 else
2777 {
2778 if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyName, desiredPropertyName) != 0)
2779 {
2780 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
2781 LogError("failure in mallocAndStrcpy_s");
2782 free(desiredProperty);
2783 result = SCHEMA_ERROR;
2784 }
2785 else
2786 {
2787 if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyType, desiredPropertyType) != 0)
2788 {
2789 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
2790 LogError("failure in mallocAndStrcpy_s");
2791 free((void*)desiredProperty->desiredPropertyName);
2792 free(desiredProperty);
2793 result = SCHEMA_ERROR;
2794 }
2795 else
2796 {
2797 if (VECTOR_push_back(handleData->desiredProperties, &desiredProperty, 1) != 0)
2798 {
2799 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
2800 LogError("failure in VECTOR_push_back");
2801 free((void*)desiredProperty->desiredPropertyType);
2802 free((void*)desiredProperty->desiredPropertyName);
2803 free(desiredProperty);
2804 result = SCHEMA_ERROR;
2805 }
2806 else
2807 {
2808 /*Codes_SRS_SCHEMA_02_029: [ Otherwise, Schema_AddModelDesiredProperty shall succeed and return SCHEMA_OK. ]*/
2809 desiredProperty->desiredPropertyFromAGENT_DATA_TYPE = desiredPropertyFromAGENT_DATA_TYPE;
2810 desiredProperty->desiredPropertInitialize = desiredPropertyInitialize;
2811 desiredProperty->desiredPropertDeinitialize = desiredPropertyDeinitialize;
2812 desiredProperty->onDesiredProperty = onDesiredProperty; /*NULL is a perfectly fine value*/
2813 desiredProperty->offset = offset;
2814 result = SCHEMA_OK;
2815 }
2816 }
2817 }
2818 }
2819 }
2820 }
2821 return result;
2822}
2823
2824
2825SCHEMA_RESULT Schema_GetModelDesiredPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* desiredPropertyCount)
2826{
2827 SCHEMA_RESULT result;
2828 /*Codes_SRS_SCHEMA_02_030: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
2829 /*Codes_SRS_SCHEMA_02_031: [ If desiredPropertyCount is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
2830 if (
2831 (modelTypeHandle == NULL) ||
2832 (desiredPropertyCount == NULL)
2833 )
2834 {
2835 LogError("invalid arg: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* desiredPropertyCount=%p", modelTypeHandle, desiredPropertyCount);
2836 result = SCHEMA_INVALID_ARG;
2837 }
2838 else
2839 {
2840 /*Codes_SRS_SCHEMA_02_032: [ Otherwise, Schema_GetModelDesiredPropertyCount shall succeed and write in desiredPropertyCount the existing number of desired properties. ]*/
2841 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2842 *desiredPropertyCount = VECTOR_size(handleData->desiredProperties);
2843 result = SCHEMA_OK;
2844 }
2845 return result;
2846}
2847
2848SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName)
2849{
2850 SCHEMA_DESIRED_PROPERTY_HANDLE result;
2851 /*Codes_SRS_SCHEMA_02_034: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
2852 /*Codes_SRS_SCHEMA_02_035: [ If desiredPropertyName is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
2853 if (
2854 (modelTypeHandle == NULL) ||
2855 (desiredPropertyName == NULL)
2856 )
2857 {
2858 LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p", modelTypeHandle, desiredPropertyName);
2859 result = NULL;
2860 }
2861 else
2862 {
2863 /*Codes_SRS_SCHEMA_02_036: [ If a desired property having the name desiredPropertyName exists then Schema_GetModelDesiredPropertyByName shall succeed and return a non-NULL value. ]*/
2864 /*Codes_SRS_SCHEMA_02_037: [ Otherwise, Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
2865 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2866 SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName);
2867 if (temp == NULL)
2868 {
2869 LogError("no such desired property by name %s", desiredPropertyName);
2870 result = NULL;
2871 }
2872 else
2873 {
2874 result = *temp;
2875 }
2876 }
2877 return result;
2878}
2879
2880SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
2881{
2882 SCHEMA_DESIRED_PROPERTY_HANDLE result;
2883 /*Codes_SRS_SCHEMA_02_038: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/
2884 if (modelTypeHandle == NULL)
2885 {
2886 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%lu", modelTypeHandle, (unsigned long)index);
2887 result = NULL;
2888 }
2889 else
2890 {
2891 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2892 /*Codes_SRS_SCHEMA_02_039: [ If index is outside the range for existing indexes of desire properties, then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/
2893 /*Codes_SRS_SCHEMA_02_040: [ Otherwise, Schema_GetModelDesiredPropertyByIndex shall succeed and return a non-NULL value. ]*/
2894 SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_element(handleData->desiredProperties, index);
2895 if (temp == NULL)
2896 {
2897 LogError("VECTOR_element produced NULL (likely out of bounds index)");
2898 result = NULL;
2899 }
2900 else
2901 {
2902 result = *temp;
2903 }
2904 }
2905 return result;
2906}
2907
2908bool Schema_ModelDesiredPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyPath)
2909{
2910 bool result;
2911 /*Codes_SRS_SCHEMA_02_041: [ If modelTypeHandle is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
2912 /*Codes_SRS_SCHEMA_02_042: [ If desiredPropertyPath is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
2913 if (
2914 (modelTypeHandle == NULL) ||
2915 (desiredPropertyPath == NULL)
2916 )
2917 {
2918 LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyPath=%p", modelTypeHandle, desiredPropertyPath);
2919 result = false;
2920 }
2921 else
2922 {
2923 const char* slashPos;
2924
2925 /*Codes_SRS_SCHEMA_02_044: [ If the desired property cannot be found Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
2926 result = false;
2927
2928 /*Codes_SRS_SCHEMA_02_043: [ desiredPropertyPath shall be assumed to be in the format model1/model2/.../desiredPropertyName. ]*/
2929 if (*desiredPropertyPath == '/')
2930 {
2931 desiredPropertyPath++;
2932 }
2933
2934 do
2935 {
2936 const char* endPos;
2937 size_t i;
2938 size_t modelCount;
2939 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
2940
2941 slashPos = strchr(desiredPropertyPath, '/');
2942 endPos = slashPos;
2943 if (endPos == NULL)
2944 {
2945 endPos = &desiredPropertyPath[strlen(desiredPropertyPath)];
2946 }
2947
2948 modelCount = VECTOR_size(modelType->models);
2949 for (i = 0; i < modelCount; i++)
2950 {
2951 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
2952 if ((strncmp(childModel->propertyName, desiredPropertyPath, endPos - desiredPropertyPath) == 0) &&
2953 (strlen(childModel->propertyName) == (size_t)(endPos - desiredPropertyPath)))
2954 {
2955 /* found */
2956 modelTypeHandle = childModel->modelHandle;
2957 break;
2958 }
2959 }
2960
2961 if (i < modelCount)
2962 {
2963 /* model found, check if there is more in the path */
2964 if (slashPos == NULL)
2965 {
2966 /*Codes_SRS_SCHEMA_02_045: [ If the path desiredPropertyPath points to a sub-model, Schema_ModelDesiredPropertyByPathExists shall succeed and true. ]*/
2967 /* this is the last one, so this is the thing we were looking for */
2968 result = true;
2969 break;
2970 }
2971 else
2972 {
2973 /* continue looking, there's more */
2974 desiredPropertyPath = slashPos + 1;
2975 }
2976 }
2977 else
2978 {
2979 /* no model found, let's see if this is a property */
2980 result = (VECTOR_find_if(modelType->desiredProperties, desiredPropertyExists, desiredPropertyPath) != NULL);
2981 if (!result)
2982 {
2983 LogError("no such desired property \"%s\"", desiredPropertyPath);
2984 }
2985 break;
2986 }
2987 } while (slashPos != NULL);
2988 }
2989 return result;
2990}
2991
2992const char* Schema_GetModelDesiredPropertyType(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
2993{
2994 const char* result;
2995 /*Codes_SRS_SCHEMA_02_062: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredPropertyType shall fail and return NULL. ]*/
2996 if (desiredPropertyHandle == NULL)
2997 {
2998 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
2999 result = NULL;
3000 }
3001 else
3002 {
3003 /*Codes_SRS_SCHEMA_02_063: [ Otherwise, Schema_GetModelDesiredPropertyType shall return the type of the desired property. ]*/
3004 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
3005 result = desirePropertyHandleData->desiredPropertyType;
3006 }
3007 return result;
3008}
3009
3010pfDesiredPropertyFromAGENT_DATA_TYPE Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
3011{
3012 pfDesiredPropertyFromAGENT_DATA_TYPE result;
3013 if (desiredPropertyHandle == NULL)
3014 {
3015 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
3016 result = NULL;
3017 }
3018 else
3019 {
3020 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
3021 result = desirePropertyHandleData->desiredPropertyFromAGENT_DATA_TYPE;
3022 }
3023 return result;
3024}
3025
3026pfOnDesiredProperty Schema_GetModelDesiredProperty_pfOnDesiredProperty(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
3027{
3028 pfOnDesiredProperty result;
3029 /*Codes_SRS_SCHEMA_02_084: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return NULL. ]*/
3030 if (desiredPropertyHandle == NULL)
3031 {
3032 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
3033 result = NULL;
3034 }
3035 else
3036 {
3037 /*Codes_SRS_SCHEMA_02_085: [ Otherwise Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return the saved desired property callback. ]*/
3038 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
3039 result = desirePropertyHandleData->onDesiredProperty;
3040 }
3041 return result;
3042}
3043
3044size_t Schema_GetModelDesiredProperty_offset(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
3045{
3046 size_t result;
3047 /*Codes_SRS_SCHEMA_02_060: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_offset shall fail and return 0. ]*/
3048 if (desiredPropertyHandle == NULL)
3049 {
3050 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
3051 result = 0;
3052 }
3053 else
3054 {
3055 /*Codes_SRS_SCHEMA_02_061: [ Otherwise Schema_GetModelDesiredProperty_offset shall succeed and return the offset. ]*/
3056 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
3057 result = desirePropertyHandleData->offset;
3058 }
3059 return result;
3060}
3061
3062static bool modelInModelExists(const void* element, const void* value)
3063{
3064 MODEL_IN_MODEL* modelInModel = (MODEL_IN_MODEL*)element;
3065 return (strcmp(modelInModel->propertyName, value) == 0);
3066}
3067
3068SCHEMA_MODEL_ELEMENT Schema_GetModelElementByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* elementName)
3069{
3070 SCHEMA_MODEL_ELEMENT result;
3071 /*Codes_SRS_SCHEMA_02_076: [ If modelTypeHandle is NULL then Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_SEARCH_INVALID_ARG. ]*/
3072 /*Codes_SRS_SCHEMA_02_077: [ If elementName is NULL then Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_SEARCH_INVALID_ARG. ]*/
3073 if (
3074 (modelTypeHandle == NULL) ||
3075 (elementName == NULL)
3076 )
3077 {
3078 LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* elementName=%p", modelTypeHandle, elementName);
3079 result.elementType = SCHEMA_SEARCH_INVALID_ARG;
3080 }
3081 else
3082 {
3083 SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
3084
3085 SCHEMA_DESIRED_PROPERTY_HANDLE* desiredPropertyHandle = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, elementName);
3086 if (desiredPropertyHandle != NULL)
3087 {
3088 /*Codes_SRS_SCHEMA_02_080: [ If elementName is a desired property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_DESIRED_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.desiredPropertyHandle to the handle of the desired property. ]*/
3089 result.elementType = SCHEMA_DESIRED_PROPERTY;
3090 result.elementHandle.desiredPropertyHandle = *desiredPropertyHandle;
3091 }
3092 else
3093 {
3094 size_t nProcessedProperties = 0;
3095 SCHEMA_PROPERTY_HANDLE_DATA* property = NULL;
3096 for (size_t i = 0; i < handleData->PropertyCount;i++)
3097 {
3098 property = (SCHEMA_PROPERTY_HANDLE_DATA*)(handleData->Properties[i]);
3099 if (strcmp(property->PropertyName, elementName) == 0)
3100 {
3101 i = handleData->PropertyCount; /*found it*/
3102 }
3103 else
3104 {
3105 nProcessedProperties++;
3106 }
3107 }
3108
3109 if (nProcessedProperties < handleData->PropertyCount)
3110 {
3111 /*Codes_SRS_SCHEMA_02_078: [ If elementName is a property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.propertyHandle to the handle of the property. ]*/
3112 result.elementType = SCHEMA_PROPERTY;
3113 result.elementHandle.propertyHandle = property;
3114 }
3115 else
3116 {
3117
3118 SCHEMA_REPORTED_PROPERTY_HANDLE* reportedPropertyHandle = VECTOR_find_if(handleData->reportedProperties, reportedPropertyExists, elementName);
3119 if (reportedPropertyHandle != NULL)
3120 {
3121 /*Codes_SRS_SCHEMA_02_079: [ If elementName is a reported property then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_REPORTED_PROPERTY and SCHEMA_MODEL_ELEMENT.elementHandle.reportedPropertyHandle to the handle of the reported property. ]*/
3122 result.elementType = SCHEMA_REPORTED_PROPERTY;
3123 result.elementHandle.reportedPropertyHandle = *reportedPropertyHandle;
3124 }
3125 else
3126 {
3127
3128 size_t nProcessedActions = 0;
3129 SCHEMA_ACTION_HANDLE_DATA* actionHandleData = NULL;
3130 for (size_t i = 0;i < handleData->ActionCount; i++)
3131 {
3132 actionHandleData = (SCHEMA_ACTION_HANDLE_DATA*)(handleData->Actions[i]);
3133 if (strcmp(actionHandleData->ActionName, elementName) == 0)
3134 {
3135 i = handleData->ActionCount; /*get out quickly*/
3136 }
3137 else
3138 {
3139 nProcessedActions++;
3140 }
3141 }
3142
3143 if (nProcessedActions < handleData->ActionCount)
3144 {
3145 /*Codes_SRS_SCHEMA_02_081: [ If elementName is a model action then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_MODEL_ACTION and SCHEMA_MODEL_ELEMENT.elementHandle.actionHandle to the handle of the action. ]*/
3146 result.elementType = SCHEMA_MODEL_ACTION;
3147 result.elementHandle.actionHandle = actionHandleData;
3148 }
3149 else
3150 {
3151 MODEL_IN_MODEL* modelInModel = VECTOR_find_if(handleData->models, modelInModelExists, elementName);
3152 if (modelInModel != NULL)
3153 {
3154 /*Codes_SRS_SCHEMA_02_082: [ If elementName is a model in model then Schema_GetModelElementByName shall succeed and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_MODEL_IN_MODEL and SCHEMA_MODEL_ELEMENT.elementHandle.modelHandle to the handle of the model. ]*/
3155 result.elementType = SCHEMA_MODEL_IN_MODEL;
3156 result.elementHandle.modelHandle = modelInModel->modelHandle;
3157 }
3158 else
3159 {
3160 /*Codes_SRS_SCHEMA_02_083: [ Otherwise Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_NOT_FOUND. ]*/
3161 result.elementType = SCHEMA_NOT_FOUND;
3162 }
3163 }
3164 }
3165 }
3166 }
3167 }
3168 return result;
3169}
3170
3171pfDesiredPropertyDeinitialize Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
3172{
3173 pfDesiredPropertyDeinitialize result;
3174 /*Ccodes_SRS_SCHEMA_02_064: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall fail and return NULL. ]*/
3175 if (desiredPropertyHandle == NULL)
3176 {
3177 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
3178 result = NULL;
3179 }
3180 else
3181 {
3182 /*Codes_SRS_SCHEMA_02_065: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall return a non-NULL function pointer. ]*/
3183 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
3184 result = handleData->desiredPropertDeinitialize;
3185 }
3186 return result;
3187}
3188
3189pfDesiredPropertyInitialize Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
3190{
3191 pfDesiredPropertyInitialize result;
3192 /*Codes_SRS_SCHEMA_02_066: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall fail and return NULL. ]*/
3193 if (desiredPropertyHandle == NULL)
3194 {
3195 LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
3196 result = NULL;
3197 }
3198 else
3199 {
3200 /*Codes_SRS_SCHEMA_02_067: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall return a non-NULL function pointer. ]*/
3201 SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
3202 result = handleData->desiredPropertInitialize;
3203 }
3204 return result;
3205}
3206
3207static bool SchemaHasModel(const SCHEMA_HANDLE* schemaHandle, const char* modelName)
3208{
3209 return (Schema_GetModelByName(*schemaHandle, modelName) != NULL);
3210}
3211
3212
3213SCHEMA_HANDLE Schema_GetSchemaForModel(const char* modelName)
3214{
3215 SCHEMA_HANDLE result;
3216 /*Codes_SRS_SCHEMA_02_093: [ If modelName is NULL then Schema_GetSchemaForModel shall fail and return NULL. ]*/
3217 if (modelName == NULL)
3218 {
3219 LogError("invalid arg const char* modelName=%p", modelName);
3220 result = NULL;
3221 }
3222 else
3223 {
3224 /*Codes_SRS_SCHEMA_02_094: [ Schema_GetSchemaForModel shall find the SCHEMA_HANDLE that contains a model by name modelName and if found, succeed and return that. ]*/
3225 SCHEMA_HANDLE* temp = VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHasModel, modelName);
3226
3227 if (temp == NULL)
3228 {
3229 /*Codes_SRS_SCHEMA_02_095: [ If the model is not found in any schema, then Schema_GetSchemaForModel shall fail and return NULL. ]*/
3230 LogError("unable to find a schema that has a model named %s", modelName);
3231 result = NULL;
3232 }
3233 else
3234 {
3235 /*Codes_SRS_SCHEMA_02_094: [ Schema_GetSchemaForModel shall find the SCHEMA_HANDLE that contains a model by name modelName and if found, succeed and return that. ]*/
3236 result = *temp;
3237 }
3238 }
3239
3240 return result;
3241}
3242
3243void* Schema_GetMetadata(SCHEMA_HANDLE schemaHandle)
3244{
3245 void* result;
3246 /*Codes_SRS_SCHEMA_02_091: [ If schemaHandle is NULL then Schema_GetMetadata shall fail and return NULL. ]*/
3247 if (schemaHandle == NULL)
3248 {
3249 LogError("invalid arg SCHEMA_HANDLE schemaHandle=%p", schemaHandle);
3250 result = NULL;
3251 }
3252 else
3253 {
3254 /*Codes_SRS_SCHEMA_02_092: [ Otherwise, Schema_GetMetadata shall succeed and return the saved metadata pointer. ]*/
3255 result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->metadata;
3256 }
3257 return result;
3258}
Note: See TracBrowser for help on using the repository browser.