Azure IoT / serializer

Dependents:   sht15_remote_monitoring f767zi_mqtt remote_monitoring simplesample_amqp ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers schema.c Source File

schema.c

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include <stdlib.h>
00005 #include "azure_c_shared_utility/gballoc.h"
00006 
00007 #include "schema.h"
00008 #include "azure_c_shared_utility/crt_abstractions.h"
00009 #include "azure_c_shared_utility/xlogging.h"
00010 #include "azure_c_shared_utility/vector.h"
00011 
00012 
00013 DEFINE_ENUM_STRINGS(SCHEMA_RESULT, SCHEMA_RESULT_VALUES);
00014 
00015 typedef struct SCHEMA_PROPERTY_HANDLE_DATA_TAG
00016 {
00017     const char* PropertyName;
00018     const char* PropertyType;
00019 } SCHEMA_PROPERTY_HANDLE_DATA;
00020 
00021 typedef struct SCHEMA_REPORTED_PROPERTY_HANDLE_DATA_TAG
00022 {
00023     const char* reportedPropertyName;
00024     const char* reportedPropertyType;
00025 } SCHEMA_REPORTED_PROPERTY_HANDLE_DATA;
00026 
00027 typedef struct SCHEMA_DESIRED_PROPERTY_HANDLE_DATA_TAG
00028 {
00029     pfOnDesiredProperty onDesiredProperty;
00030     pfDesiredPropertyInitialize desiredPropertInitialize;
00031     pfDesiredPropertyDeinitialize desiredPropertDeinitialize;
00032     const char* desiredPropertyName;
00033     const char* desiredPropertyType;
00034     pfDesiredPropertyFromAGENT_DATA_TYPE desiredPropertyFromAGENT_DATA_TYPE;
00035     size_t offset;
00036 } SCHEMA_DESIRED_PROPERTY_HANDLE_DATA;
00037 
00038 typedef struct SCHEMA_ACTION_ARGUMENT_HANDLE_DATA_TAG
00039 {
00040     const char* Name;
00041     const char* Type;
00042 } SCHEMA_ACTION_ARGUMENT_HANDLE_DATA;
00043 
00044 typedef struct SCHEMA_METHOD_ARGUMENT_HANDLE_DATA_TAG
00045 {
00046     char* Name;
00047     char* Type;
00048 } SCHEMA_METHOD_ARGUMENT_HANDLE_DATA;
00049 
00050 typedef struct SCHEMA_ACTION_HANDLE_DATA_TAG
00051 {
00052     const char* ActionName;
00053     size_t ArgumentCount;
00054     SCHEMA_ACTION_ARGUMENT_HANDLE* ArgumentHandles;
00055 } SCHEMA_ACTION_HANDLE_DATA;
00056 
00057 typedef struct SCHEMA_METHOD_HANDLE_DATA_TAG
00058 {
00059     char* methodName;
00060     VECTOR_HANDLE methodArguments; /*holds SCHEMA_METHOD_ARGUMENT_HANDLE*/
00061 } SCHEMA_METHOD_HANDLE_DATA;
00062 
00063 typedef struct MODEL_IN_MODEL_TAG
00064 {
00065     pfOnDesiredProperty onDesiredProperty; /*is NULL if not specified or if the model in model is not WITH_DESIRED_PROPERTY*/
00066     size_t offset; /*offset of the model in model (offsetof)*/
00067     const char* propertyName;
00068     SCHEMA_MODEL_TYPE_HANDLE modelHandle;
00069 } MODEL_IN_MODEL;
00070 
00071 typedef struct SCHEMA_MODEL_TYPE_HANDLE_DATA_TAG
00072 {
00073     VECTOR_HANDLE methods; /*holds SCHEMA_METHOD_HANDLE*/
00074     VECTOR_HANDLE desiredProperties; /*holds SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*/
00075     const char* Name;
00076     SCHEMA_HANDLE SchemaHandle;
00077     SCHEMA_PROPERTY_HANDLE* Properties;
00078     size_t PropertyCount;
00079     VECTOR_HANDLE reportedProperties; /*holds SCHEMA_REPORTED_PROPERTY_HANDLE*/
00080     SCHEMA_ACTION_HANDLE* Actions;
00081     size_t ActionCount;
00082     VECTOR_HANDLE models;
00083     size_t DeviceCount;
00084 } SCHEMA_MODEL_TYPE_HANDLE_DATA;
00085 
00086 typedef struct SCHEMA_STRUCT_TYPE_HANDLE_DATA_TAG
00087 {
00088     const char* Name;
00089     SCHEMA_PROPERTY_HANDLE* Properties;
00090     size_t PropertyCount;
00091 } SCHEMA_STRUCT_TYPE_HANDLE_DATA;
00092 
00093 typedef struct SCHEMA_HANDLE_DATA_TAG
00094 {
00095     void* metadata;
00096     const char* Namespace;
00097     SCHEMA_MODEL_TYPE_HANDLE* ModelTypes;
00098     size_t ModelTypeCount;
00099     SCHEMA_STRUCT_TYPE_HANDLE* StructTypes;
00100     size_t StructTypeCount;
00101 } SCHEMA_HANDLE_DATA;
00102 
00103 static VECTOR_HANDLE g_schemas = NULL;
00104 
00105 static void DestroyProperty(SCHEMA_PROPERTY_HANDLE propertyHandle)
00106 {
00107     SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
00108     free((void*)propertyType->PropertyName);
00109     free((void*)propertyType->PropertyType);
00110     free(propertyType);
00111 }
00112 
00113 static void DestroyActionArgument(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
00114 {
00115     SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
00116     if (actionArgument != NULL)
00117     {
00118         free((void*)actionArgument->Name);
00119         free((void*)actionArgument->Type);
00120         free(actionArgument);
00121     }
00122 }
00123 
00124 static void DestroyMethodArgument(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
00125 {
00126     free(methodArgumentHandle->Name);
00127     free(methodArgumentHandle->Type);
00128     free(methodArgumentHandle);
00129 }
00130 
00131 static void DestroyAction(SCHEMA_ACTION_HANDLE actionHandle)
00132 {
00133     SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
00134     if (action != NULL)
00135     {
00136         size_t j;
00137 
00138         for (j = 0; j < action->ArgumentCount; j++)
00139         {
00140             DestroyActionArgument(action->ArgumentHandles[j]);
00141         }
00142         free(action->ArgumentHandles);
00143 
00144         free((void*)action->ActionName);
00145         free(action);
00146     }
00147 }
00148 
00149 static void DestroyMethod(SCHEMA_METHOD_HANDLE methodHandle)
00150 {
00151     size_t nArguments = VECTOR_size(methodHandle->methodArguments);
00152 
00153     for (size_t j = 0; j < nArguments; j++)
00154     {
00155         SCHEMA_METHOD_ARGUMENT_HANDLE* methodArgumentHandle = VECTOR_element(methodHandle->methodArguments, j);
00156         DestroyMethodArgument(*methodArgumentHandle);
00157     }
00158     free(methodHandle->methodName);
00159     VECTOR_destroy(methodHandle->methodArguments);
00160     free(methodHandle);
00161 }
00162 
00163 static void DestroyMethods(SCHEMA_MODEL_TYPE_HANDLE modelHandle)
00164 {
00165     size_t nMethods = VECTOR_size(modelHandle->methods);
00166 
00167     for (size_t j = 0; j < nMethods; j++)
00168     {
00169         SCHEMA_METHOD_HANDLE* methodHandle = VECTOR_element(modelHandle->methods, j);
00170         DestroyMethod(*methodHandle);
00171     }
00172     VECTOR_destroy(modelHandle->methods);
00173 }
00174 
00175 
00176 static void DestroyStruct(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle)
00177 {
00178     size_t i;
00179     SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
00180     if (structType != NULL)
00181     {
00182         for (i = 0; i < structType->PropertyCount; i++)
00183         {
00184             DestroyProperty(structType->Properties[i]);
00185         }
00186         free(structType->Properties);
00187 
00188         free((void*)structType->Name);
00189 
00190         free(structType);
00191     }
00192 }
00193 
00194 static void DestroyModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
00195 {
00196     SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
00197     size_t i, nReportedProperties;
00198 
00199     free((void*)modelType->Name);
00200     modelType->Name = NULL;
00201 
00202     for (i = 0; i < modelType->PropertyCount; i++)
00203     {
00204         DestroyProperty(modelType->Properties[i]);
00205     }
00206 
00207     free(modelType->Properties);
00208 
00209     for (i = 0; i < modelType->ActionCount; i++)
00210     {
00211         DestroyAction(modelType->Actions[i]);
00212     }
00213 
00214     DestroyMethods(modelType);
00215 
00216     /*destroy the vector holding the added models. This does not destroy the said models, however, their names shall be*/
00217     for (i = 0; i < VECTOR_size(modelType->models); i++)
00218     {
00219         MODEL_IN_MODEL* temp = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
00220         free((void*)temp->propertyName);
00221     }
00222 
00223     nReportedProperties = VECTOR_size(modelType->reportedProperties);
00224     for (i = 0;i < nReportedProperties;i++)
00225     {
00226         SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->reportedProperties, i);
00227         free((void*)reportedProperty->reportedPropertyName);
00228         free((void*)reportedProperty->reportedPropertyType);
00229         free(reportedProperty);
00230     }
00231     VECTOR_destroy(modelType->reportedProperties);
00232 
00233     size_t nDesiredProperties = VECTOR_size(modelType->desiredProperties);
00234     for (i = 0;i < nDesiredProperties;i++)
00235     {
00236         SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA **)VECTOR_element(modelType->desiredProperties, i);
00237         free((void*)desiredProperty->desiredPropertyName);
00238         free((void*)desiredProperty->desiredPropertyType);
00239         free(desiredProperty);
00240     }
00241     VECTOR_destroy(modelType->desiredProperties);
00242 
00243     VECTOR_clear(modelType->models);
00244     VECTOR_destroy(modelType->models);
00245 
00246     free(modelType->Actions);
00247     free(modelType);
00248 }
00249 
00250 static SCHEMA_RESULT AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType, const char* name, const char* type)
00251 {
00252     SCHEMA_RESULT result;
00253 
00254     /* Codes_SRS_SCHEMA_99_013:[If any of the arguments is NULL, Schema_AddModelProperty shall return SCHEMA_INVALID_ARG.] */
00255     if ((modelType == NULL) ||
00256         (name == NULL) ||
00257         (type == NULL))
00258     {
00259         result = SCHEMA_INVALID_ARG;
00260         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00261     }
00262     else
00263     {
00264         size_t i;
00265 
00266         /* 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.] */
00267         for (i = 0; i < modelType->PropertyCount; i++)
00268         {
00269             SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
00270             if (strcmp(property->PropertyName, name) == 0)
00271             {
00272                 break;
00273             }
00274         }
00275 
00276         if (i < modelType->PropertyCount)
00277         {
00278             result = SCHEMA_DUPLICATE_ELEMENT;
00279             LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00280         }
00281         else
00282         {
00283             SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (modelType->PropertyCount + 1));
00284             if (newProperties == NULL)
00285             {
00286                 /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
00287                 result = SCHEMA_ERROR;
00288                 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00289             }
00290             else
00291             {
00292                 SCHEMA_PROPERTY_HANDLE_DATA* newProperty;
00293 
00294                 modelType->Properties = newProperties;
00295                 if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL)
00296                 {
00297                     /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
00298                     result = SCHEMA_ERROR;
00299                     LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00300                 }
00301                 else
00302                 {
00303                     if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, name) != 0)
00304                     {
00305                         /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
00306                         free(newProperty);
00307                         result = SCHEMA_ERROR;
00308                         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00309                     }
00310                     else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, type) != 0)
00311                     {
00312                         /* Codes_SRS_SCHEMA_99_014:[On any other error, Schema_AddModelProperty shall return SCHEMA_ERROR.] */
00313                         free((void*)newProperty->PropertyName);
00314                         free(newProperty);
00315                         result = SCHEMA_ERROR;
00316                         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00317                     }
00318                     else
00319                     {
00320                         modelType->Properties[modelType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty;
00321                         modelType->PropertyCount++;
00322 
00323                         /* Codes_SRS_SCHEMA_99_012:[On success, Schema_AddModelProperty shall return SCHEMA_OK.] */
00324                         result = SCHEMA_OK;
00325                     }
00326                 }
00327 
00328                 /* If possible, reduce the memory of over allocation */
00329                 if (result != SCHEMA_OK)
00330                 {
00331                     if (modelType->PropertyCount > 0)
00332                     {
00333                         SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(modelType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * modelType->PropertyCount);
00334                         if (oldProperties == NULL)
00335                         {
00336                             result = SCHEMA_ERROR;
00337                             LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00338                         }
00339                         else
00340                         {
00341                             modelType->Properties = oldProperties;
00342                         }
00343                     }
00344                     else
00345                     {
00346                         modelType->Properties = NULL;
00347                     }
00348                 }
00349             }
00350         }
00351     }
00352 
00353     return result;
00354 }
00355 
00356 static bool SchemaHandlesMatch(const SCHEMA_HANDLE* handle, const SCHEMA_HANDLE* otherHandle)
00357 {
00358     return (*handle == *otherHandle);
00359 }
00360 
00361 static bool SchemaNamespacesMatch(const SCHEMA_HANDLE* handle, const char* schemaNamespace)
00362 {
00363     const SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)*handle;
00364     return (strcmp(schema->Namespace, schemaNamespace) == 0);
00365 }
00366 
00367 /* Codes_SRS_SCHEMA_99_001:[Schema_Create shall initialize a schema with a given namespace.] */
00368 SCHEMA_HANDLE Schema_Create(const char* schemaNamespace, void* metadata)
00369 {
00370     SCHEMA_HANDLE_DATA* result;
00371     /*Codes_SRS_SCHEMA_02_090: [ If metadata is NULL then Schema_Create shall fail and return NULL. ]*/
00372     /* Codes_SRS_SCHEMA_99_004:[If schemaNamespace is NULL, Schema_Create shall fail.] */
00373     if (
00374         (schemaNamespace == NULL)||
00375         (metadata == NULL)
00376         )
00377     {
00378         /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
00379         LogError("invalid arg const char* schemaNamespace=%p, void* metadata=%p",schemaNamespace, metadata);
00380         result = NULL;
00381     }
00382     else
00383     {
00384         if (g_schemas == NULL && (g_schemas = VECTOR_create(sizeof(SCHEMA_HANDLE_DATA*) ) ) == NULL)
00385         {
00386             /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
00387             result = NULL;
00388             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00389         }
00390         else if ((result = (SCHEMA_HANDLE_DATA*)malloc(sizeof(SCHEMA_HANDLE_DATA))) == NULL)
00391         {
00392             /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
00393             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00394         }
00395         else if (mallocAndStrcpy_s((char**)&result->Namespace, schemaNamespace) != 0)
00396         {
00397             /* Codes_SRS_SCHEMA_99_003:[On failure, NULL shall be returned.] */
00398             free(result);
00399             result = NULL;
00400             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00401         }
00402         else if (VECTOR_push_back(g_schemas, &result, 1) != 0)
00403         {
00404             free((void*)result->Namespace);
00405             free(result);
00406             result = NULL;
00407             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00408         }
00409         else
00410         {
00411             /* Codes_SRS_SCHEMA_99_002:[On success a non-NULL handle to the newly created schema shall be returned.] */
00412             result->ModelTypes = NULL;
00413             result->ModelTypeCount = 0;
00414             result->StructTypes = NULL;
00415             result->StructTypeCount = 0;
00416             result->metadata = metadata;
00417         }
00418     }
00419 
00420     return (SCHEMA_HANDLE)result;
00421 }
00422 
00423 size_t Schema_GetSchemaCount(void)
00424 {
00425     /* Codes_SRS_SCHEMA_99_153: [Schema_GetSchemaCount shall return the number of "active" schemas (all schemas created with Schema_Create
00426     in the current process, for which Schema_Destroy has not been called).] */
00427     return VECTOR_size(g_schemas);
00428 }
00429 
00430 SCHEMA_HANDLE Schema_GetSchemaByNamespace(const char* schemaNamespace)
00431 {
00432     /* Codes_SRS_SCHEMA_99_151: [If no active schema matches the schemaNamespace argument, Schema_GetSchemaByNamespace shall return NULL.] */
00433     SCHEMA_HANDLE result = NULL;
00434 
00435     /* Codes_SRS_SCHEMA_99_150: [If the schemaNamespace argument is NULL, Schema_GetSchemaByNamespace shall return NULL.] */
00436     if (schemaNamespace != NULL)
00437     {
00438         SCHEMA_HANDLE* handle = (g_schemas==NULL)?NULL:(SCHEMA_HANDLE*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaNamespacesMatch, schemaNamespace);
00439         if (handle != NULL)
00440         {
00441             /* Codes_SRS_SCHEMA_99_148: [Schema_GetSchemaByNamespace shall search all active schemas and return the schema with the
00442                namespace given by the schemaNamespace argument.] */
00443             result = *handle;
00444         }
00445     }
00446 
00447     return result;
00448 }
00449 
00450 const char* Schema_GetSchemaNamespace(SCHEMA_HANDLE schemaHandle)
00451 {
00452     const char* result;
00453 
00454     /* Codes_SRS_SCHEMA_99_130: [If the schemaHandle argument is NULL, Schema_GetSchemaNamespace shall return NULL.] */
00455     if (schemaHandle == NULL)
00456     {
00457         result = NULL;
00458     }
00459     else
00460     {
00461         /* Codes_SRS_SCHEMA_99_129: [Schema_GetSchemaNamespace shall return the namespace for the schema identified by schemaHandle.] */
00462         result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->Namespace;
00463     }
00464 
00465     return result;
00466 }
00467 
00468 void Schema_Destroy(SCHEMA_HANDLE schemaHandle)
00469 {
00470     /* Codes_SRS_SCHEMA_99_006:[If the schemaHandle is NULL, Schema_Destroy shall do nothing.] */
00471     if (schemaHandle != NULL)
00472     {
00473         SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
00474         size_t i;
00475 
00476         /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */
00477         for (i = 0; i < schema->ModelTypeCount; i++)
00478         {
00479             DestroyModel(schema->ModelTypes[i]);
00480         }
00481 
00482         free(schema->ModelTypes);
00483 
00484         /* Codes_SRS_SCHEMA_99_005:[Schema_Destroy shall free all resources associated with a schema.] */
00485         for (i = 0; i < schema->StructTypeCount; i++)
00486         {
00487             DestroyStruct(schema->StructTypes[i]);
00488         }
00489 
00490         free(schema->StructTypes);
00491         free((void*)schema->Namespace);
00492         free(schema);
00493 
00494         schema = (SCHEMA_HANDLE_DATA*)VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHandlesMatch, &schemaHandle);
00495         if (schema != NULL)
00496         {
00497             VECTOR_erase(g_schemas, schema, 1);
00498         }
00499         // If the g_schema is empty then destroy it
00500         if (VECTOR_size(g_schemas) == 0)
00501         {
00502             VECTOR_destroy(g_schemas);
00503             g_schemas = NULL;
00504         }
00505     }
00506 }
00507 
00508 SCHEMA_RESULT Schema_DestroyIfUnused(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
00509 {
00510     SCHEMA_RESULT result;
00511 
00512     /* Codes_SRS_SCHEMA_07_189: [If modelHandle variable is NULL Schema_DestroyIfUnused shall do nothing.] */
00513     if (modelTypeHandle != NULL)
00514     {
00515         SCHEMA_HANDLE schemaHandle = Schema_GetSchemaForModelType(modelTypeHandle);
00516         if (schemaHandle == NULL)
00517         {
00518             result = SCHEMA_ERROR;
00519         }
00520         else
00521         {
00522             SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
00523             size_t nIndex;
00524 
00525             /* 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.] */
00526             for (nIndex = 0; nIndex < schema->ModelTypeCount; nIndex++)
00527             {
00528                 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[nIndex];
00529                 if (modelType->DeviceCount > 0)
00530                     break;
00531             }
00532             /* Codes_SRS_SCHEMA_07_191: [If 1 or more DeviceCount variables are > 0 then Schema_DestroyIfUnused shall do nothing.] */
00533             if (nIndex == schema->ModelTypeCount)
00534             {
00535                 Schema_Destroy(schemaHandle);
00536                 result = SCHEMA_OK;
00537             }
00538             else
00539             {
00540                 result = SCHEMA_MODEL_IN_USE;
00541             }
00542         }
00543     }
00544     else
00545     {
00546         result = SCHEMA_INVALID_ARG;
00547     }
00548     return result;
00549 }
00550 
00551 SCHEMA_RESULT Schema_AddDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
00552 {
00553     SCHEMA_RESULT result;
00554     if (modelTypeHandle == NULL)
00555     {
00556         /* Codes_SRS_SCHEMA_07_187: [Schema_AddDeviceRef shall return SCHEMA_INVALID_ARG if modelTypeHandle is NULL.] */
00557         result = SCHEMA_INVALID_ARG;
00558         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00559     }
00560     else
00561     {
00562         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
00563         /* Codes_SRS_SCHEMA_07_188: [If the modelTypeHandle is nonNULL, Schema_AddDeviceRef shall increment the SCHEMA_MODEL_TYPE_HANDLE_DATA DeviceCount variable.] */
00564         model->DeviceCount++;
00565         result = SCHEMA_OK;
00566     }
00567     return result;
00568 }
00569 
00570 SCHEMA_RESULT Schema_ReleaseDeviceRef(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
00571 {
00572     SCHEMA_RESULT result;
00573     /* Codes_SRS_SCHEMA_07_184: [Schema_DeviceRelease shall do nothing if the supplied modelHandle is NULL.] */
00574     if (modelTypeHandle == NULL)
00575     {
00576         result = SCHEMA_INVALID_ARG;
00577         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00578     }
00579     else
00580     {
00581         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
00582         if (model->DeviceCount > 0)
00583         {
00584             /* Codes_SRS_SCHEMA_07_186: [On a nonNULL SCHEMA_MODEL_TYPE_HANDLE if the DeviceCount variable is > 0 then the variable will be decremented.] */
00585             model->DeviceCount--;
00586             result = SCHEMA_OK;
00587         }
00588         else
00589         {
00590 result = SCHEMA_DEVICE_COUNT_ZERO;
00591 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
00592         }
00593     }
00594     return result;
00595 }
00596 
00597 /* Codes_SRS_SCHEMA_99_007:[Schema_CreateModelType shall create a new model type and return a handle to it.] */
00598 SCHEMA_MODEL_TYPE_HANDLE Schema_CreateModelType(SCHEMA_HANDLE schemaHandle, const char* modelName)
00599 {
00600     SCHEMA_MODEL_TYPE_HANDLE result;
00601 
00602     /* Codes_SRS_SCHEMA_99_010:[If any of the arguments is NULL, Schema_CreateModelType shall fail.] */
00603     if ((schemaHandle == NULL) ||
00604         (modelName == NULL))
00605     {
00606         /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00607         result = NULL;
00608         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
00609     }
00610     else
00611     {
00612         SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
00613 
00614         /* Codes_SRS_SCHEMA_99_100: [Schema_CreateModelType shall return SCHEMA_DUPLICATE_ELEMENT if modelName already exists.] */
00615         size_t i;
00616         for (i = 0; i < schema->ModelTypeCount; i++)
00617         {
00618             SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)(schema->ModelTypes[i]);
00619             if (strcmp(model->Name, modelName) == 0)
00620             {
00621                 break;
00622             }
00623         }
00624 
00625         if (i < schema->ModelTypeCount)
00626         {
00627             /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00628             result = NULL;
00629             LogError("%s Model Name already exists", modelName);
00630         }
00631 
00632         else
00633         {
00634             SCHEMA_MODEL_TYPE_HANDLE* newModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * (schema->ModelTypeCount + 1));
00635             if (newModelTypes == NULL)
00636             {
00637                 /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00638                 result = NULL;
00639                 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00640             }
00641             else
00642             {
00643                 SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType;
00644                 schema->ModelTypes = newModelTypes;
00645 
00646                 if ((modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)malloc(sizeof(SCHEMA_MODEL_TYPE_HANDLE_DATA))) == NULL)
00647                 {
00648 
00649                     /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00650                     result = NULL;
00651                     LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00652                 }
00653                 else if (mallocAndStrcpy_s((char**)&modelType->Name, modelName) != 0)
00654                 {
00655                     /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00656                     result = NULL;
00657                     free(modelType);
00658                     LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00659                 }
00660                 else
00661                 {
00662                     modelType->models = VECTOR_create(sizeof(MODEL_IN_MODEL));
00663                     if (modelType->models == NULL)
00664                     {
00665                         /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00666                         LogError("unable to VECTOR_create");
00667                         free((void*)modelType->Name);
00668                         free((void*)modelType);
00669                         result = NULL;
00670                     }
00671                     else
00672                     {
00673                         if ((modelType->reportedProperties = VECTOR_create(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE))) == NULL)
00674                         {
00675                             /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00676                             LogError("failed to VECTOR_create (reported properties)");
00677                             VECTOR_destroy(modelType->models);
00678                             free((void*)modelType->Name);
00679                             free((void*)modelType);
00680                             result = NULL;
00681 
00682                         }
00683                         else
00684                         {
00685                             /* Codes_SRS_SCHEMA_99_009:[On failure, Schema_CreateModelType shall return NULL.] */
00686                             if ((modelType->desiredProperties = VECTOR_create(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE))) == NULL)
00687                             {
00688                                 LogError("failure in VECTOR_create (desired properties)");
00689                                 VECTOR_destroy(modelType->reportedProperties);
00690                                 VECTOR_destroy(modelType->models);
00691                                 free((void*)modelType->Name);
00692                                 free((void*)modelType);
00693                                 result = NULL;
00694                             }
00695                             else
00696                             {
00697                                 if ((modelType->methods = VECTOR_create(sizeof(SCHEMA_METHOD_HANDLE))) == NULL)
00698                                 {
00699                                     LogError("failure in VECTOR_create (desired properties)");
00700                                     VECTOR_destroy(modelType->desiredProperties);
00701                                     VECTOR_destroy(modelType->reportedProperties);
00702                                     VECTOR_destroy(modelType->models);
00703                                     free((void*)modelType->Name);
00704                                     free((void*)modelType);
00705                                     result = NULL;
00706                                 }
00707                                 else
00708                                 {
00709                                     modelType->PropertyCount = 0;
00710                                     modelType->Properties = NULL;
00711                                     modelType->ActionCount = 0;
00712                                     modelType->Actions = NULL;
00713                                     modelType->SchemaHandle = schemaHandle;
00714                                     modelType->DeviceCount = 0;
00715 
00716                                     schema->ModelTypes[schema->ModelTypeCount] = modelType;
00717                                     schema->ModelTypeCount++;
00718                                     /* Codes_SRS_SCHEMA_99_008:[On success, a non-NULL handle shall be returned.] */
00719                                     result = (SCHEMA_MODEL_TYPE_HANDLE)modelType;
00720                                 }
00721                             }
00722                         }
00723                     }
00724                 }
00725 
00726                 /* If possible, reduce the memory of over allocation */
00727                 if ((result == NULL) &&(schema->ModelTypeCount>0))
00728                 {
00729                     SCHEMA_MODEL_TYPE_HANDLE* oldModelTypes = (SCHEMA_MODEL_TYPE_HANDLE*)realloc(schema->ModelTypes, sizeof(SCHEMA_MODEL_TYPE_HANDLE) * schema->ModelTypeCount);
00730                     if (oldModelTypes == NULL)
00731                     {
00732                         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00733                     }
00734                     else
00735                     {
00736                         schema->ModelTypes = oldModelTypes;
00737                     }
00738                 }
00739             }
00740         }
00741     }
00742 
00743     return result;
00744 }
00745 
00746 SCHEMA_HANDLE Schema_GetSchemaForModelType(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
00747 {
00748     SCHEMA_HANDLE result;
00749 
00750     if (modelTypeHandle == NULL)
00751     {
00752         /* Codes_SRS_SCHEMA_99_132: [If the modelTypeHandle argument is NULL, Schema_GetSchemaForModelType shall return NULL.] */
00753         result = NULL;
00754     }
00755     else
00756     {
00757         /* Codes_SRS_SCHEMA_99_131: [Schema_GetSchemaForModelType returns the schema handle for a given model type.] */
00758         result = ((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle)->SchemaHandle;
00759     }
00760 
00761     return result;
00762 }
00763 
00764 /* Codes_SRS_SCHEMA_99_011:[Schema_AddModelProperty shall add one property to the model type identified by modelTypeHandle.] */
00765 SCHEMA_RESULT Schema_AddModelProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, const char* propertyType)
00766 {
00767     return AddModelProperty((SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle, propertyName, propertyType);
00768 }
00769 
00770 static bool reportedPropertyExists(const void* element, const void* value)
00771 {
00772     SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = *(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA**)element;
00773     return (strcmp(reportedProperty->reportedPropertyName, value) == 0);
00774 }
00775 
00776 SCHEMA_RESULT Schema_AddModelReportedProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName, const char* reportedPropertyType)
00777 {
00778     SCHEMA_RESULT result;
00779     /*Codes_SRS_SCHEMA_02_001: [ If modelTypeHandle is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
00780     /*Codes_SRS_SCHEMA_02_002: [ If reportedPropertyName is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
00781     /*Codes_SRS_SCHEMA_02_003: [ If reportedPropertyType is NULL then Schema_AddModelReportedProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
00782     if (
00783         (modelTypeHandle == NULL) ||
00784         (reportedPropertyName == NULL) ||
00785         (reportedPropertyType == NULL)
00786         )
00787     {
00788         LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p, const char* reportedPropertyType=%p", modelTypeHandle, reportedPropertyName, reportedPropertyType);
00789         result = SCHEMA_INVALID_ARG;
00790     }
00791     else
00792     {
00793         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
00794         /*Codes_SRS_SCHEMA_02_004: [ If reportedPropertyName has already been added then Schema_AddModelReportedProperty shall fail and return SCHEMA_PROPERTY_ELEMENT_EXISTS. ]*/
00795         if (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName) != NULL)
00796         {
00797             LogError("unable to add reportedProperty %s because it already exists", reportedPropertyName);
00798             result = SCHEMA_DUPLICATE_ELEMENT;
00799         }
00800         else
00801         {
00802             /*Codes_SRS_SCHEMA_02_005: [ Schema_AddModelReportedProperty shall record reportedPropertyName and reportedPropertyType. ]*/
00803             SCHEMA_REPORTED_PROPERTY_HANDLE_DATA* reportedProperty = (SCHEMA_REPORTED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_REPORTED_PROPERTY_HANDLE_DATA));
00804             if (reportedProperty == NULL)
00805             {
00806                 /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
00807                 LogError("unable to malloc");
00808                 result = SCHEMA_ERROR;
00809             }
00810             else
00811             {
00812                 if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyName, reportedPropertyName) != 0)
00813                 {
00814                     /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
00815                     LogError("unable to mallocAndStrcpy_s");
00816                     free(reportedProperty);
00817                     result = SCHEMA_ERROR;
00818                 }
00819                 else
00820                 {
00821                     if (mallocAndStrcpy_s((char**)&reportedProperty->reportedPropertyType, reportedPropertyType) != 0)
00822                     {
00823                         /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
00824                         LogError("unable to mallocAndStrcpy_s");
00825                         free((void*)reportedProperty->reportedPropertyName);
00826                         free(reportedProperty);
00827                         result = SCHEMA_ERROR;
00828                     }
00829                     else
00830                     {
00831                         if (VECTOR_push_back(modelType->reportedProperties, &reportedProperty, 1) != 0)
00832                         {
00833                             /*Codes_SRS_SCHEMA_02_006: [ If any error occurs then Schema_AddModelReportedProperty shall fail and return SCHEMA_ERROR. ]*/
00834                             LogError("unable to VECTOR_push_back");
00835                             free((void*)reportedProperty->reportedPropertyType);
00836                             free((void*)reportedProperty->reportedPropertyName);
00837                             free(reportedProperty);
00838                             result = SCHEMA_ERROR;
00839                         }
00840                         else
00841                         {
00842                             /*Codes_SRS_SCHEMA_02_007: [ Otherwise Schema_AddModelReportedProperty shall succeed and return SCHEMA_OK. ]*/
00843                             result = SCHEMA_OK;
00844                         }
00845                     }
00846                 }
00847             }
00848         }
00849     }
00850     return result;
00851 }
00852 
00853 SCHEMA_ACTION_HANDLE Schema_CreateModelAction(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName)
00854 {
00855     SCHEMA_ACTION_HANDLE result;
00856 
00857     /* Codes_SRS_SCHEMA_99_104: [If any of the modelTypeHandle or actionName arguments is NULL, Schema_CreateModelAction shall return NULL.] */
00858     if ((modelTypeHandle == NULL) ||
00859         (actionName == NULL))
00860     {
00861         result = NULL;
00862         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
00863     }
00864     else
00865     {
00866         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
00867         size_t i;
00868 
00869         /* 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.] */
00870         for (i = 0; i < modelType->ActionCount; i++)
00871         {
00872             SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i];
00873             if (strcmp(action->ActionName, actionName) == 0)
00874             {
00875                 break;
00876             }
00877         }
00878 
00879         if (i < modelType->ActionCount)
00880         {
00881             result = NULL;
00882             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT));
00883         }
00884         else
00885         {
00886             /* Codes_SRS_SCHEMA_99_102: [Schema_CreateModelAction shall add one action to the model type identified by modelTypeHandle.] */
00887             SCHEMA_ACTION_HANDLE* newActions = (SCHEMA_ACTION_HANDLE*)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * (modelType->ActionCount + 1));
00888             if (newActions == NULL)
00889             {
00890                 /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
00891                 result = NULL;
00892                 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00893             }
00894             else
00895             {
00896                 SCHEMA_ACTION_HANDLE_DATA* newAction;
00897                 modelType->Actions = newActions;
00898 
00899                 /* Codes_SRS_SCHEMA_99_103: [On success, Schema_CreateModelAction shall return a none-NULL SCHEMA_ACTION_HANDLE to the newly created action.] */
00900                 if ((newAction = (SCHEMA_ACTION_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_HANDLE_DATA))) == NULL)
00901                 {
00902                     /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
00903                     result = NULL;
00904                     LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00905                 }
00906                 else
00907                 {
00908                     if (mallocAndStrcpy_s((char**)&newAction->ActionName, actionName) != 0)
00909                     {
00910                         /* Codes_SRS_SCHEMA_99_106: [On any other error, Schema_CreateModelAction shall return NULL.]*/
00911                         free(newAction);
00912                         result = NULL;
00913                         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00914                     }
00915                     else
00916                     {
00917                         newAction->ArgumentCount = 0;
00918                         newAction->ArgumentHandles = NULL;
00919 
00920                         modelType->Actions[modelType->ActionCount] = newAction;
00921                         modelType->ActionCount++;
00922                         result = (SCHEMA_ACTION_HANDLE)(newAction);
00923                     }
00924 
00925                     /* If possible, reduce the memory of over allocation */
00926                     if (result == NULL)
00927                     {
00928                         if (modelType->ActionCount > 0)
00929                         {
00930                             SCHEMA_ACTION_HANDLE *oldActions = (SCHEMA_ACTION_HANDLE *)realloc(modelType->Actions, sizeof(SCHEMA_ACTION_HANDLE) * modelType->ActionCount);
00931                             if (oldActions == NULL)
00932                             {
00933                                 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
00934                             }
00935                             else
00936                             {
00937                                 modelType->Actions = oldActions;
00938                             }
00939                         }
00940                         else
00941                         {
00942                             modelType->Actions = NULL;
00943                         }
00944                     }
00945                 }
00946             }
00947         }
00948     }
00949     return result;
00950 }
00951 
00952 
00953 static bool methodExists(const void* element, const void* value)
00954 {
00955     const SCHEMA_METHOD_HANDLE* method = (const SCHEMA_METHOD_HANDLE*)element;
00956     return (strcmp((*method)->methodName, value) == 0);
00957 }
00958 
00959 
00960 SCHEMA_METHOD_HANDLE Schema_CreateModelMethod(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName)
00961 {
00962     SCHEMA_METHOD_HANDLE result;
00963 
00964     /*Codes_SRS_SCHEMA_02_096: [ If modelTypeHandle is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/
00965     /*Codes_SRS_SCHEMA_02_097: [ If methodName is NULL then Schema_CreateModelMethod shall fail and return NULL. ]*/
00966     if ((modelTypeHandle == NULL) ||
00967         (methodName == NULL))
00968     {
00969         result = NULL;
00970         LogError("invalid argument: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName);
00971     }
00972     else
00973     {
00974         /*Codes_SRS_SCHEMA_02_103: [ If methodName already exists, then Schema_CreateModelMethod shall fail and return NULL. ]*/
00975         if (VECTOR_find_if(modelTypeHandle->methods, methodExists, methodName) != NULL)
00976         {
00977             LogError("method %s already exists", methodName);
00978             result = NULL;
00979         }
00980         else
00981         {
00982             /*Codes_SRS_SCHEMA_02_098: [ Schema_CreateModelMethod shall allocate the space for the method. ]*/
00983             result = malloc(sizeof(SCHEMA_METHOD_HANDLE_DATA));
00984             if (result == NULL)
00985             {
00986                 LogError("failed to malloc");
00987                 /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
00988                 /*return as is*/
00989             }
00990             else
00991             {
00992                 /*Codes_SRS_SCHEMA_02_099: [ Schema_CreateModelMethod shall create a VECTOR that will hold the method's arguments. ]*/
00993                 result->methodArguments = VECTOR_create(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE));
00994                 if (result->methodArguments == NULL)
00995                 {
00996                     /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
00997                     LogError("failure in VECTOR_create");
00998                     free(result);
00999                     result = NULL;
01000                 }
01001                 else
01002                 {
01003                     /*Codes_SRS_SCHEMA_02_100: [ Schema_CreateModelMethod shall clone methodName ]*/
01004                     if (mallocAndStrcpy_s(&result->methodName, methodName) != 0)
01005                     {
01006                         /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
01007                         LogError("failure in mallocAndStrcpy_s");
01008                         VECTOR_destroy(result->methodArguments);
01009                         free(result);
01010                         result = NULL;
01011                     }
01012                     else
01013                     {
01014                         /*Codes_SRS_SCHEMA_02_101: [ Schema_CreateModelMethod shall add the new created method to the model's list of methods. ]*/
01015                         if (VECTOR_push_back(modelTypeHandle->methods, &result, 1) != 0)
01016                         {
01017                             /*Codes_SRS_SCHEMA_02_102: [ If any of the above fails, then Schema_CreateModelMethod shall fail and return NULL. ]*/
01018                             LogError("failure in VECTOR_push_back");
01019                             free(result->methodName);
01020                             VECTOR_destroy(result->methodArguments);
01021                             free(result);
01022                             result = NULL;
01023                         }
01024                         else
01025                         {
01026                             /*Codes_SRS_SCHEMA_02_104: [ Otherwise, Schema_CreateModelMethod shall succeed and return a non-NULL SCHEMA_METHOD_HANDLE. ]*/
01027                             /*return as is*/
01028                         }
01029                     }
01030                 }
01031             }
01032         }
01033     }
01034     return result;
01035 }
01036 
01037 
01038 SCHEMA_RESULT Schema_AddModelActionArgument(SCHEMA_ACTION_HANDLE actionHandle, const char* argumentName, const char* argumentType)
01039 {
01040     SCHEMA_RESULT result;
01041 
01042     /* Codes_SRS_SCHEMA_99_109: [If any of the arguments is NULL, Schema_AddModelActionArgument shall return SCHEMA_INVALID_ARG.] */
01043     if ((actionHandle == NULL) ||
01044         (argumentName == NULL) ||
01045         (argumentType == NULL))
01046     {
01047         result = SCHEMA_INVALID_ARG;
01048         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01049     }
01050     else
01051     {
01052         SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
01053 
01054         /* 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.] */
01055         /* Codes_SRS_SCHEMA_99_111: [Schema_AddModelActionArgument shall accept arguments with different names of the same type.]  */
01056         size_t i;
01057         for (i = 0; i < action->ArgumentCount; i++)
01058         {
01059             SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)action->ArgumentHandles[i];
01060             if (strcmp((actionArgument->Name), argumentName) == 0)
01061             {
01062                 break;
01063             }
01064         }
01065 
01066         if (i < action->ArgumentCount)
01067         {
01068             result = SCHEMA_DUPLICATE_ELEMENT;
01069             LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01070         }
01071         else
01072         {
01073             /* Codes_SRS_SCHEMA_99_107: [Schema_AddModelActionArgument shall add one argument name & type to an action identified by actionHandle.]  */
01074             SCHEMA_ACTION_ARGUMENT_HANDLE* newArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE*)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * (action->ArgumentCount + 1));
01075             if (newArguments == NULL)
01076             {
01077                 /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
01078                 result = SCHEMA_ERROR;
01079                 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01080             }
01081             else
01082             {
01083                 action->ArgumentHandles = newArguments;
01084 
01085                 SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* newActionArgument;
01086 
01087                 action->ArgumentHandles = newArguments;
01088                 if ((newActionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)malloc(sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE_DATA))) == NULL)
01089                 {
01090                     /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
01091                     result = SCHEMA_ERROR;
01092                     LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01093                 }
01094                 else
01095                 {
01096                     if (mallocAndStrcpy_s((char**)&newActionArgument->Name, argumentName) != 0)
01097                     {
01098                         /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
01099                         free(newActionArgument);
01100                         result = SCHEMA_ERROR;
01101                         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01102                     }
01103                     else if (mallocAndStrcpy_s((char**)&newActionArgument->Type, argumentType) != 0)
01104                     {
01105                         /* Codes_SRS_SCHEMA_99_112: [On any other error, Schema_ AddModelActionArgumet shall return SCHEMA_ERROR.] */
01106                         free((void*)newActionArgument->Name);
01107                         free(newActionArgument);
01108                         result = SCHEMA_ERROR;
01109                         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01110                     }
01111                     else
01112                     {
01113                         /* 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.] */
01114                         action->ArgumentHandles[action->ArgumentCount] = newActionArgument;
01115                         action->ArgumentCount++;
01116 
01117                         /* Codes_SRS_SCHEMA_99_108: [On success, Schema_AddModelActionArgunent shall return SCHEMA_OK.] */
01118                         result = SCHEMA_OK;
01119                     }
01120                 }
01121 
01122                 /* If possible, reduce the memory of over allocation */
01123                 if (result == SCHEMA_ERROR)
01124                 {
01125                     if (action->ArgumentCount > 0)
01126                     {
01127                         SCHEMA_ACTION_ARGUMENT_HANDLE *oldArguments = (SCHEMA_ACTION_ARGUMENT_HANDLE *)realloc(action->ArgumentHandles, sizeof(SCHEMA_ACTION_ARGUMENT_HANDLE) * action->ArgumentCount);
01128                         if (oldArguments == NULL)
01129                         {
01130                             LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
01131                         }
01132                         else
01133                         {
01134                             action->ArgumentHandles = oldArguments;
01135                         }
01136                     }
01137                     else
01138                     {
01139                         action->ArgumentHandles = NULL;
01140                     }
01141                 }
01142             }
01143         }
01144     }
01145     return result;
01146 }
01147 
01148 static bool methodFindArgumentByBame(const void* element, const void* value)
01149 {
01150     /*element is a pointer to SCHEMA_METHOD_ARGUMENT_HANDLE*/
01151     const SCHEMA_METHOD_ARGUMENT_HANDLE* decodedElement = (const SCHEMA_METHOD_ARGUMENT_HANDLE*)element;
01152     const char* name = (const char*)value;
01153     return (strcmp((*decodedElement)->Name, name) == 0);
01154 }
01155 
01156 SCHEMA_RESULT Schema_AddModelMethodArgument(SCHEMA_METHOD_HANDLE methodHandle, const char* argumentName, const char* argumentType)
01157 {
01158     SCHEMA_RESULT result;
01159     /*Codes_SRS_SCHEMA_02_105: [ If methodHandle is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
01160     /*Codes_SRS_SCHEMA_02_106: [ If argumentName is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
01161     /*Codes_SRS_SCHEMA_02_107: [ If argumentType is NULL then Schema_AddModelMethodArgument shall fail and return SCHEMA_INVALID_ARG. ]*/
01162     if ((methodHandle == NULL) ||
01163         (argumentName == NULL) ||
01164         (argumentType == NULL))
01165     {
01166         result = SCHEMA_INVALID_ARG;
01167         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01168     }
01169     else
01170     {
01171         /*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. ]*/
01172         if (VECTOR_find_if(methodHandle->methodArguments, methodFindArgumentByBame, argumentName) != NULL)
01173         {
01174             LogError("an argument with name %s already exists", argumentName);
01175             result = SCHEMA_INVALID_ARG;
01176         }
01177         else
01178         {
01179             /*Codes_SRS_SCHEMA_02_109: [ Schema_AddModelMethodArgument shall allocate memory for the new argument. ]*/
01180             SCHEMA_METHOD_ARGUMENT_HANDLE_DATA* argument = malloc(sizeof(SCHEMA_METHOD_ARGUMENT_HANDLE_DATA));
01181             if (argument == NULL)
01182             {
01183                 /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
01184                 LogError("failure to malloc");
01185                 result = SCHEMA_ERROR;
01186             }
01187             else
01188             {
01189                 /*Codes_SRS_SCHEMA_02_110: [ Schema_AddModelMethodArgument shall clone methodHandle. ]*/
01190                 if (mallocAndStrcpy_s(&argument->Name, argumentName) != 0)
01191                 {
01192                     /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
01193                     LogError("failure in mallocAndStrcpy_s");
01194                     free(argument);
01195                     result = SCHEMA_ERROR;
01196                 }
01197                 else
01198                 {
01199                     /*Codes_SRS_SCHEMA_02_111: [ Schema_AddModelMethodArgument shall clone argumentType. ]*/
01200                     if (mallocAndStrcpy_s(&argument->Type, argumentType) != 0)
01201                     {
01202                         /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
01203                         LogError("failure in mallocAndStrcpy_s");
01204                         free(argument->Name);
01205                         free(argument);
01206                         result = SCHEMA_ERROR;
01207                     }
01208                     else
01209                     {
01210                         /*Codes_SRS_SCHEMA_02_112: [ Schema_AddModelMethodArgument shall add the created argument to the method's list of arguments. ]*/
01211                         if (VECTOR_push_back(methodHandle->methodArguments, &argument, 1) != 0)
01212                         {
01213                             /*Codes_SRS_SCHEMA_02_113: [ If any of the above operations fails, then Schema_AddModelMethodArgument shall fail and return SCHEMA_ERROR. ]*/
01214                             LogError("failure in VECTOR_push_back");
01215                             free(argument->Name);
01216                             free(argument->Type);
01217                             free(argument);
01218                             result = SCHEMA_ERROR;
01219                         }
01220                         else
01221                         {
01222                             /*Codes_SRS_SCHEMA_02_114: [ Otherwise, Schema_AddModelMethodArgument shall succeed and return SCHEMA_OK. ]*/
01223                             result = SCHEMA_OK;
01224                         }
01225                     }
01226                 }
01227             }
01228         }
01229     }
01230     return result;
01231 }
01232 
01233 SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
01234 {
01235     SCHEMA_PROPERTY_HANDLE result;
01236 
01237     /* 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.] */
01238     if ((modelTypeHandle == NULL) ||
01239         (propertyName == NULL))
01240     {
01241         result = NULL;
01242         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01243     }
01244     else
01245     {
01246         size_t i;
01247         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01248 
01249         /* 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.] */
01250         for (i = 0; i < modelType->PropertyCount; i++)
01251         {
01252             SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
01253             if (strcmp(modelProperty->PropertyName, propertyName) == 0)
01254             {
01255                 break;
01256             }
01257         }
01258 
01259         if (i == modelType->PropertyCount)
01260         {
01261             /* 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.] */
01262             result = NULL;
01263             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
01264         }
01265         else
01266         {
01267             result = (SCHEMA_PROPERTY_HANDLE)(modelType->Properties[i]);
01268         }
01269     }
01270 
01271     return result;
01272 }
01273 
01274 SCHEMA_RESULT Schema_GetModelPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* propertyCount)
01275 {
01276     SCHEMA_RESULT result;
01277 
01278     /* Codes_SRS_SCHEMA_99_092: [Schema_GetModelPropertyCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
01279     if ((modelTypeHandle == NULL) ||
01280         (propertyCount == NULL))
01281     {
01282         result = SCHEMA_INVALID_ARG;
01283     }
01284     else
01285     {
01286         /* Codes_SRS_SCHEMA_99_089: [Schema_GetModelPropertyCount shall provide the number of properties defined in the model type identified by modelTypeHandle.] */
01287         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01288 
01289         /* Codes_SRS_SCHEMA_99_090: [The count shall be provided via the out argument propertyCount.]*/
01290         *propertyCount = modelType->PropertyCount;
01291 
01292         /* Codes_SRS_SCHEMA_99_091: [On success, Schema_GetModelPropertyCount shall return SCHEMA_OK.] */
01293         result = SCHEMA_OK;
01294     }
01295 
01296     return result;
01297 }
01298 
01299 SCHEMA_RESULT Schema_GetModelReportedPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* reportedPropertyCount)
01300 {
01301     SCHEMA_RESULT result;
01302     /*Codes_SRS_SCHEMA_02_008: [ If parameter modelTypeHandle is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
01303     /*Codes_SRS_SCHEMA_02_009: [ If parameter reportedPropertyCount is NULL then Schema_GetModelReportedPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
01304     if (
01305         (modelTypeHandle == NULL)||
01306         (reportedPropertyCount==NULL)
01307         )
01308     {
01309         LogError("SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* reportedPropertyCount=%p", modelTypeHandle, reportedPropertyCount);
01310         result = SCHEMA_INVALID_ARG;
01311     }
01312     else
01313     {
01314         /*Codes_SRS_SCHEMA_02_010: [ Schema_GetModelReportedPropertyCount shall provide in reportedPropertyCount the number of reported properties and return SCHEMA_OK. ]*/
01315         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01316         *reportedPropertyCount = VECTOR_size(modelType->reportedProperties);
01317         result = SCHEMA_OK;
01318     }
01319     return result;
01320 }
01321 
01322 SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyName)
01323 {
01324     SCHEMA_REPORTED_PROPERTY_HANDLE result;
01325     /*Codes_SRS_SCHEMA_02_011: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
01326     /*Codes_SRS_SCHEMA_02_012: [ If argument reportedPropertyName is NULL then Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
01327     if(
01328         (modelTypeHandle == NULL) ||
01329         (reportedPropertyName == NULL)
01330         )
01331     {
01332         LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyName=%p", modelTypeHandle, reportedPropertyName);
01333         result = NULL;
01334     }
01335     else
01336     {
01337         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01338         /*Codes_SRS_SCHEMA_02_013: [ If reported property by the name reportedPropertyName exists then Schema_GetModelReportedPropertyByName shall succeed and return a non-NULL value. ]*/
01339         /*Codes_SRS_SCHEMA_02_014: [ Otherwise Schema_GetModelReportedPropertyByName shall fail and return NULL. ]*/
01340         if((result = VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyName))==NULL)
01341         {
01342             LogError("a reported property with name \"%s\" does not exist", reportedPropertyName);
01343         }
01344         else
01345         {
01346             /*return as is*/
01347         }
01348     }
01349     return result;
01350 }
01351 
01352 SCHEMA_REPORTED_PROPERTY_HANDLE Schema_GetModelReportedPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
01353 {
01354     SCHEMA_REPORTED_PROPERTY_HANDLE result;
01355     /*Codes_SRS_SCHEMA_02_015: [ If argument modelTypeHandle is NULL then Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/
01356     if (modelTypeHandle == NULL)
01357     {
01358         LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%zu", modelTypeHandle, index);
01359         result = NULL;
01360     }
01361     else
01362     {
01363         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01364 
01365         /*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. ]*/
01366         /*Codes_SRS_SCHEMA_02_017: [ Otherwise Schema_GetModelReportedPropertyByIndex shall fail and return NULL. ]*/
01367         if ((result = VECTOR_element(modelType->reportedProperties, index)) == NULL)
01368         {
01369             LogError("index %zu is invalid", index);
01370         }
01371         else
01372         {
01373             /*return as is*/
01374         }
01375     }
01376     return result;
01377 }
01378 
01379 SCHEMA_PROPERTY_HANDLE Schema_GetModelPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
01380 {
01381     SCHEMA_PROPERTY_HANDLE result;
01382     SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01383 
01384     /* 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.] */
01385     if ((modelTypeHandle == NULL) ||
01386         (index >= modelType->PropertyCount))
01387     {
01388         result = NULL;
01389         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01390     }
01391     else
01392     {
01393         /* 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.] */
01394         /* 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.] */
01395         result = modelType->Properties[index];
01396     }
01397 
01398     return result;
01399 }
01400 
01401 SCHEMA_ACTION_HANDLE Schema_GetModelActionByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* actionName)
01402 {
01403     SCHEMA_ACTION_HANDLE result;
01404 
01405     /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */
01406     if ((modelTypeHandle == NULL) ||
01407         (actionName == NULL))
01408     {
01409         result = NULL;
01410         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01411     }
01412     else
01413     {
01414         size_t i;
01415         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01416 
01417         /* 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.] */
01418         for (i = 0; i < modelType->ActionCount; i++)
01419         {
01420             SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)modelType->Actions[i];
01421             if (strcmp(modelAction->ActionName, actionName) == 0)
01422             {
01423                 break;
01424             }
01425         }
01426 
01427         if (i == modelType->ActionCount)
01428         {
01429             /* Codes_SRS_SCHEMA_99_041:[Schema_GetModelActionByName shall return NULL if unable to find a matching action, if any of the arguments are NULL.] */
01430             result = NULL;
01431             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
01432         }
01433         else
01434         {
01435             result = modelType->Actions[i];
01436         }
01437     }
01438 
01439     return result;
01440 }
01441 
01442 static bool matchModelMethod(const void* element, const void* value)
01443 {
01444     /*element is a pointer to SCHEMA_METHOD_HANDLE_DATA*/
01445     const SCHEMA_METHOD_HANDLE* decodedElement = (const SCHEMA_METHOD_HANDLE* )element;
01446     const char* name = (const char*)value;
01447     return (strcmp((*decodedElement)->methodName, name) == 0);
01448 }
01449 
01450 SCHEMA_METHOD_HANDLE Schema_GetModelMethodByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* methodName)
01451 {
01452     SCHEMA_METHOD_HANDLE result;
01453 
01454     /*Codes_SRS_SCHEMA_02_115: [ If modelTypeHandle is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/
01455     /*Codes_SRS_SCHEMA_02_116: [ If methodName is NULL then Schema_GetModelMethodByName shall fail and return NULL. ]*/
01456     if ((modelTypeHandle == NULL) ||
01457         (methodName == NULL))
01458     {
01459         result = NULL;
01460         LogError("invalid arguments SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* methodName=%p", modelTypeHandle, methodName);
01461     }
01462     else
01463     {
01464         /*Codes_SRS_SCHEMA_02_117: [ If a method with the name methodName exists then Schema_GetModelMethodByName shall succeed and returns its handle. ]*/
01465         SCHEMA_METHOD_HANDLE* found = VECTOR_find_if(modelTypeHandle->methods, matchModelMethod, methodName);
01466         if (found == NULL)
01467         {
01468             /*Codes_SRS_SCHEMA_02_118: [ Otherwise, Schema_GetModelMethodByName shall fail and return NULL. ]*/
01469             LogError("no such method by name = %s", methodName);
01470             result = NULL;
01471         }
01472         else
01473         {
01474             result = *found;
01475         }
01476     }
01477 
01478     return result;
01479 }
01480 
01481 SCHEMA_RESULT Schema_GetModelActionCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* actionCount)
01482 {
01483     SCHEMA_RESULT result;
01484 
01485     /* Codes_SRS_SCHEMA_99_045:[If any of the modelTypeHandle or actionCount arguments is NULL, Schema_GetModelActionCount shall return SCHEMA_INVALID_ARG.] */
01486     if ((modelTypeHandle == NULL) ||
01487         (actionCount == NULL))
01488     {
01489         result = SCHEMA_INVALID_ARG;
01490         LogError("(result=%s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01491     }
01492     else
01493     {
01494         /* Codes_SRS_SCHEMA_99_042:[Schema_GetModelActionCount shall provide the total number of actions defined in a model type identified by the modelTypeHandle.] */
01495         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01496 
01497         /* Codes_SRS_SCHEMA_99_043:[The count shall be provided via the out argument actionCount.] */
01498         *actionCount = modelType->ActionCount;
01499 
01500         /* Codes_SRS_SCHEMA_99_044:[On success, Schema_GetModelActionCount shall return SCHEMA_OK.] */
01501         result = SCHEMA_OK;
01502     }
01503 
01504     return result;
01505 }
01506 
01507 SCHEMA_ACTION_HANDLE Schema_GetModelActionByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
01508 {
01509     SCHEMA_ACTION_HANDLE result;
01510     SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
01511 
01512     /* 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.] */
01513     if ((modelType == NULL) ||
01514         (index >= modelType->ActionCount))
01515     {
01516         result = NULL;
01517         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01518     }
01519     else
01520     {
01521         /* 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.] */
01522         /* 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.] */
01523         result = modelType->Actions[index];
01524     }
01525 
01526     return result;
01527 }
01528 
01529 const char* Schema_GetModelActionName(SCHEMA_ACTION_HANDLE actionHandle)
01530 {
01531     const char* result;
01532 
01533     /* Codes_SRS_SCHEMA_99_050:[If the actionHandle is NULL, Schema_GetModelActionName shall return NULL.] */
01534     if (actionHandle == NULL)
01535     {
01536         result = NULL;
01537         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01538     }
01539     else
01540     {
01541         SCHEMA_ACTION_HANDLE_DATA* action = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
01542         /* Codes_SRS_SCHEMA_99_049:[Schema_GetModelActionName shall return the action name for a given action handle.] */
01543         result = action->ActionName;
01544     }
01545 
01546     return result;
01547 }
01548 
01549 SCHEMA_RESULT Schema_GetModelActionArgumentCount(SCHEMA_ACTION_HANDLE actionHandle, size_t* argumentCount)
01550 {
01551     SCHEMA_RESULT result;
01552 
01553     /* Codes_SRS_SCHEMA_99_054:[If any argument is NULL, Schema_GetModelActionArgumentCount shall return SCHEMA_INVALID_ARG.] */
01554     if ((actionHandle == NULL) ||
01555         (argumentCount == NULL))
01556     {
01557         result = SCHEMA_INVALID_ARG;
01558         LogError("(result=%s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01559     }
01560     else
01561     {
01562         SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
01563 
01564         /* Codes_SRS_SCHEMA_99_051:[Schema_GetModelActionArgumentCount shall provide the number of arguments for a specific schema action identified by actionHandle.] */
01565         /* Codes_SRS_SCHEMA_99_052:[The argument count shall be provided via the out argument argumentCount.] */
01566         *argumentCount = modelAction->ArgumentCount;
01567 
01568         /* Codes_SRS_SCHEMA_99_053:[On success, Schema_GetModelActionArgumentCount shall return SCHEMA_OK.] */
01569         result = SCHEMA_OK;
01570     }
01571 
01572     return result;
01573 }
01574 
01575 SCHEMA_RESULT Schema_GetModelMethodArgumentCount(SCHEMA_METHOD_HANDLE methodHandle, size_t* argumentCount)
01576 {
01577     SCHEMA_RESULT result;
01578 
01579     /*Codes_SRS_SCHEMA_02_119: [ If methodHandle is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/
01580     /*Codes_SRS_SCHEMA_02_120: [ If argumentCount is NULL then Schema_GetModelMethodArgumentCount shall fail and return SCHEMA_INVALID_ARG. ]*/
01581     if ((methodHandle == NULL) ||
01582         (argumentCount == NULL))
01583     {
01584         result = SCHEMA_INVALID_ARG;
01585         LogError("(result=%s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01586     }
01587     else
01588     {
01589         /*Codes_SRS_SCHEMA_02_121: [ Otherwise, Schema_GetModelMethodArgumentCount shall succeed, return in argumentCount the number of arguments for the method and return SCHEMA_OK. ]*/
01590         *argumentCount = VECTOR_size(methodHandle->methodArguments);
01591         result = SCHEMA_OK;
01592     }
01593 
01594     return result;
01595 }
01596 
01597 
01598 SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByName(SCHEMA_ACTION_HANDLE actionHandle, const char* actionArgumentName)
01599 {
01600     SCHEMA_ACTION_ARGUMENT_HANDLE result;
01601 
01602     /* 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.] */
01603     if ((actionHandle == NULL) ||
01604         (actionArgumentName == NULL))
01605     {
01606         result = NULL;
01607         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01608     }
01609     else
01610     {
01611         /* 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.] */
01612         SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
01613         size_t i;
01614 
01615         for (i = 0; i < modelAction->ArgumentCount; i++)
01616         {
01617             SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)modelAction->ArgumentHandles[i];
01618             if (strcmp(actionArgument->Name, actionArgumentName) == 0)
01619             {
01620                 break;
01621             }
01622         }
01623 
01624         if (i == modelAction->ArgumentCount)
01625         {
01626             /* 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.] */
01627             result = NULL;
01628             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
01629         }
01630         else
01631         {
01632             /* Codes_SRS_SCHEMA_99_117: [Schema_GetModelActionArgumentByName shall return a non-NULL handle corresponding to an action argument identified by the actionHandle and actionArgumentName.] */
01633             result = modelAction->ArgumentHandles[i];
01634         }
01635     }
01636 
01637     return result;
01638 }
01639 
01640 SCHEMA_ACTION_ARGUMENT_HANDLE Schema_GetModelActionArgumentByIndex(SCHEMA_ACTION_HANDLE actionHandle, size_t argumentIndex)
01641 {
01642     SCHEMA_ACTION_ARGUMENT_HANDLE result;
01643     SCHEMA_ACTION_HANDLE_DATA* modelAction = (SCHEMA_ACTION_HANDLE_DATA*)actionHandle;
01644 
01645     /* 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.] */
01646     if ((actionHandle == NULL) ||
01647         (argumentIndex >= modelAction->ArgumentCount))
01648     {
01649         result = NULL;
01650         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01651     }
01652     else
01653     {
01654         /* 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.] */
01655         result = modelAction->ArgumentHandles[argumentIndex];
01656     }
01657 
01658     return result;
01659 }
01660 
01661 SCHEMA_METHOD_ARGUMENT_HANDLE Schema_GetModelMethodArgumentByIndex(SCHEMA_METHOD_HANDLE methodHandle, size_t argumentIndex)
01662 {
01663     SCHEMA_METHOD_ARGUMENT_HANDLE result;
01664 
01665     /*Codes_SRS_SCHEMA_02_122: [ If methodHandle is NULL then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/
01666     if (methodHandle == NULL)
01667     {
01668         result = NULL;
01669         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01670     }
01671     else
01672     {
01673         /*Codes_SRS_SCHEMA_02_123: [ If argumentIndex does not exist then Schema_GetModelMethodArgumentByIndex shall fail and return NULL. ]*/
01674         SCHEMA_METHOD_ARGUMENT_HANDLE *temp = VECTOR_element(methodHandle->methodArguments, argumentIndex);
01675         if (temp == NULL)
01676         {
01677             result = NULL;
01678         }
01679         else
01680         {
01681             /*Codes_SRS_SCHEMA_02_124: [ Otherwise, Schema_GetModelMethodArgumentByIndex shall succeed and return a non-NULL value. ]*/
01682             result = *temp;
01683         }
01684     }
01685 
01686     return result;
01687 }
01688 
01689 
01690 const char* Schema_GetActionArgumentName(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
01691 {
01692     const char* result;
01693     /* Codes_SRS_SCHEMA_99_114: [Schema_GetActionArgumentName shall return NULL if actionArgumentHandle is NULL.] */
01694     if (actionArgumentHandle == NULL)
01695     {
01696         result = NULL;
01697         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01698     }
01699     else
01700     {
01701         /* Codes_SRS_SCHEMA_99_113: [Schema_GetActionArgumentName shall return the argument name identified by the actionArgumentHandle.] */
01702         SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
01703         result = actionArgument->Name;
01704     }
01705     return result;
01706 }
01707 
01708 const char* Schema_GetMethodArgumentName(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
01709 {
01710     const char* result;
01711     /*Codes_SRS_SCHEMA_02_125: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentName shall fail and return NULL. ]*/
01712     if (methodArgumentHandle == NULL)
01713     {
01714         result = NULL;
01715         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01716     }
01717     else
01718     {
01719         /*Codes_SRS_SCHEMA_02_126: [ Otherwise, Schema_GetMethodArgumentName shall succeed and return a non-NULL value. ]*/
01720         result = methodArgumentHandle->Name;
01721     }
01722     return result;
01723 }
01724 
01725 
01726 const char* Schema_GetActionArgumentType(SCHEMA_ACTION_ARGUMENT_HANDLE actionArgumentHandle)
01727 {
01728     const char* result;
01729     /* Codes_SRS_SCHEMA_99_116: [Schema_GetActionArgumentType shall return NULL if actionArgumentHandle is NULL.] */
01730     if (actionArgumentHandle == NULL)
01731     {
01732         result = NULL;
01733         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01734     }
01735     else
01736     {
01737         /* Codes_SRS_SCHEMA_99_115: [Schema_GetActionArgumentType shall return the argument type identified by the actionArgumentHandle.] */
01738         SCHEMA_ACTION_ARGUMENT_HANDLE_DATA* actionArgument = (SCHEMA_ACTION_ARGUMENT_HANDLE_DATA*)actionArgumentHandle;
01739         result = actionArgument->Type;
01740     }
01741     return result;
01742 }
01743 
01744 const char* Schema_GetMethodArgumentType(SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle)
01745 {
01746     const char* result;
01747     /*Codes_SRS_SCHEMA_02_127: [ If methodArgumentHandle is NULL then Schema_GetMethodArgumentType shall fail and return NULL. ]*/
01748     if (methodArgumentHandle == NULL)
01749     {
01750         result = NULL;
01751         LogError("invalid argument SCHEMA_METHOD_ARGUMENT_HANDLE methodArgumentHandle=%p", methodArgumentHandle);
01752     }
01753     else
01754     {
01755         /*Codes_SRS_SCHEMA_02_128: [ Otherwise, Schema_GetMethodArgumentType shall succeed and return a non-NULL value. ]*/
01756         result = methodArgumentHandle->Type;
01757     }
01758     return result;
01759 }
01760 
01761 
01762 SCHEMA_STRUCT_TYPE_HANDLE Schema_CreateStructType(SCHEMA_HANDLE schemaHandle, const char* typeName)
01763 {
01764     SCHEMA_STRUCT_TYPE_HANDLE result;
01765     SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
01766 
01767     /* Codes_SRS_SCHEMA_99_060:[If any of the arguments is NULL, Schema_CreateStructType shall return NULL.] */
01768     if ((schema == NULL) ||
01769         (typeName == NULL))
01770     {
01771         result = NULL;
01772         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01773     }
01774     else
01775     {
01776         SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType;
01777         size_t i;
01778 
01779         /* Codes_SRS_SCHEMA_99_061:[If a struct type with the same name already exists, Schema_CreateStructType shall return NULL.] */
01780         for (i = 0; i < schema->StructTypeCount; i++)
01781         {
01782             structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i];
01783             if (strcmp(structType->Name, typeName) == 0)
01784             {
01785                 break;
01786             }
01787         }
01788 
01789         if (i < schema->StructTypeCount)
01790         {
01791             result = NULL;
01792             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_DUPLICATE_ELEMENT));
01793         }
01794         else
01795         {
01796             SCHEMA_STRUCT_TYPE_HANDLE* newStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE*)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * (schema->StructTypeCount + 1));
01797             if (newStructTypes == NULL)
01798             {
01799                 /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
01800                 result = NULL;
01801                 LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
01802             }
01803             else
01804             {
01805                 schema->StructTypes = newStructTypes;
01806                 if ((structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)malloc(sizeof(SCHEMA_STRUCT_TYPE_HANDLE_DATA))) == NULL)
01807                 {
01808                     /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
01809                     result = NULL;
01810                     LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
01811                 }
01812                 else if (mallocAndStrcpy_s((char**)&structType->Name, typeName) != 0)
01813                 {
01814                     /* Codes_SRS_SCHEMA_99_066:[On any other error, Schema_CreateStructType shall return NULL.] */
01815                     result = NULL;
01816                     free(structType);
01817                     LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
01818                 }
01819                 else
01820                 {
01821                     /* Codes_SRS_SCHEMA_99_057:[Schema_CreateStructType shall create a new struct type and return a handle to it.] */
01822                     schema->StructTypes[schema->StructTypeCount] = structType;
01823                     schema->StructTypeCount++;
01824                     structType->PropertyCount = 0;
01825                     structType->Properties = NULL;
01826 
01827                     /* Codes_SRS_SCHEMA_99_058:[On success, a non-NULL handle shall be returned.] */
01828                     result = (SCHEMA_STRUCT_TYPE_HANDLE)structType;
01829                 }
01830 
01831                 /* If possible, reduce the memory of over allocation */
01832                 if (result == NULL)
01833                 {
01834                     if (schema->StructTypeCount > 0)
01835                     {
01836                         SCHEMA_STRUCT_TYPE_HANDLE *oldStructTypes = (SCHEMA_STRUCT_TYPE_HANDLE *)realloc(schema->StructTypes, sizeof(SCHEMA_STRUCT_TYPE_HANDLE) * schema->StructTypeCount);
01837                         if (oldStructTypes == NULL)
01838                         {
01839                             result = NULL;
01840                             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ERROR));
01841                         }
01842                         else
01843                         {
01844                             schema->StructTypes = oldStructTypes;
01845                         }
01846                     }
01847                     else
01848                     {
01849                         schema->StructTypes = NULL;
01850                     }
01851                 }
01852             }
01853         }
01854     }
01855 
01856     return result;
01857 }
01858 
01859 const char* Schema_GetStructTypeName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle)
01860 {
01861     const char* result;
01862 
01863     /* Codes_SRS_SCHEMA_99_136: [If structTypeHandle is NULL, Schema_GetStructTypeName shall return NULL.] */
01864     if (structTypeHandle == NULL)
01865     {
01866         result = NULL;
01867         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01868     }
01869     else
01870     {
01871         /* Codes_SRS_SCHEMA_99_135: [Schema_GetStructTypeName shall return the name of a struct type identified by the structTypeHandle argument.] */
01872         result = ((SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle)->Name;
01873     }
01874 
01875     return result;
01876 }
01877 
01878 SCHEMA_RESULT Schema_GetStructTypeCount(SCHEMA_HANDLE schemaHandle, size_t* structTypeCount)
01879 {
01880     SCHEMA_RESULT result;
01881 
01882     /* Codes_SRS_SCHEMA_99_140: [Schema_GetStructTypeCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
01883     if ((schemaHandle == NULL) ||
01884         (structTypeCount == NULL))
01885     {
01886         result = SCHEMA_INVALID_ARG;
01887         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01888     }
01889     else
01890     {
01891         /* Codes_SRS_SCHEMA_99_137: [Schema_GetStructTypeCount shall provide the number of structs defined in the schema identified by schemaHandle.] */
01892         SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
01893         /* Codes_SRS_SCHEMA_99_138: [The count shall be provided via the out argument structTypeCount.] */
01894         *structTypeCount = schema->StructTypeCount;
01895         /* Codes_SRS_SCHEMA_99_139: [On success, Schema_GetStructTypeCount shall return SCHEMA_OK.] */
01896         result = SCHEMA_OK;
01897     }
01898 
01899     return result;
01900 }
01901 
01902 SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByName(SCHEMA_HANDLE schemaHandle, const char* name)
01903 {
01904     SCHEMA_STRUCT_TYPE_HANDLE result;
01905     SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
01906 
01907     /* 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.] */
01908     if ((schemaHandle == NULL) ||
01909         (name == NULL))
01910     {
01911         result = NULL;
01912         LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01913     }
01914     else
01915     {
01916         size_t i;
01917 
01918         /* 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.] */
01919         for (i = 0; i < schema->StructTypeCount; i++)
01920         {
01921             SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)schema->StructTypes[i];
01922             if (strcmp(structType->Name, name) == 0)
01923             {
01924                 break;
01925             }
01926         }
01927 
01928         if (i == schema->StructTypeCount)
01929         {
01930             /* 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.] */
01931             result = NULL;
01932             LogError("(Error code:%s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
01933         }
01934         else
01935         {
01936             result = schema->StructTypes[i];
01937         }
01938     }
01939 
01940     return result;
01941 }
01942 
01943 SCHEMA_STRUCT_TYPE_HANDLE Schema_GetStructTypeByIndex(SCHEMA_HANDLE schemaHandle, size_t index)
01944 {
01945     SCHEMA_STRUCT_TYPE_HANDLE result;
01946     SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
01947 
01948     /* 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.] */
01949     /* 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.] */
01950     if ((schemaHandle == NULL) ||
01951         (index >= schema->StructTypeCount))
01952     {
01953         result = NULL;
01954         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
01955     }
01956     else
01957     {
01958 
01959         /* 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.] */
01960         /* 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.] */
01961         result = schema->StructTypes[index];
01962     }
01963     return result;
01964 }
01965 
01966 SCHEMA_RESULT Schema_AddStructTypeProperty(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName, const char* propertyType)
01967 {
01968     SCHEMA_RESULT result;
01969 
01970     /* Codes_SRS_SCHEMA_99_072:[If any of the arguments is NULL, Schema_AddStructTypeProperty shall return SCHEMA_INVALID_ARG.] */
01971     if ((structTypeHandle == NULL) ||
01972         (propertyName == NULL) ||
01973         (propertyType == NULL))
01974     {
01975         result = SCHEMA_INVALID_ARG;
01976         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01977     }
01978     else
01979     {
01980         size_t i;
01981         SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
01982 
01983         /* 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.] */
01984         for (i = 0; i < structType->PropertyCount; i++)
01985         {
01986             SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i];
01987             if (strcmp(property->PropertyName, propertyName) == 0)
01988             {
01989                 break;
01990             }
01991         }
01992 
01993         if (i < structType->PropertyCount)
01994         {
01995             result = SCHEMA_DUPLICATE_ELEMENT;
01996             LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
01997         }
01998         else
01999         {
02000             SCHEMA_PROPERTY_HANDLE* newProperties = (SCHEMA_PROPERTY_HANDLE*)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * (structType->PropertyCount + 1));
02001             if (newProperties == NULL)
02002             {
02003                 result = SCHEMA_ERROR;
02004                 LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02005             }
02006             else
02007             {
02008                 SCHEMA_PROPERTY_HANDLE_DATA* newProperty;
02009 
02010                 structType->Properties = newProperties;
02011                 if ((newProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_PROPERTY_HANDLE_DATA))) == NULL)
02012                 {
02013                     result = SCHEMA_ERROR;
02014                     LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02015                 }
02016                 else
02017                 {
02018                     if (mallocAndStrcpy_s((char**)&newProperty->PropertyName, propertyName) != 0)
02019                     {
02020                         free(newProperty);
02021                         result = SCHEMA_ERROR;
02022                         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02023                     }
02024                     else if (mallocAndStrcpy_s((char**)&newProperty->PropertyType, propertyType) != 0)
02025                     {
02026                         free((void*)newProperty->PropertyName);
02027                         free(newProperty);
02028                         result = SCHEMA_ERROR;
02029                         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02030                     }
02031                     else
02032                     {
02033                         /* Codes_SRS_SCHEMA_99_070:[Schema_AddStructTypeProperty shall add one property to the struct type identified by structTypeHandle.] */
02034                         structType->Properties[structType->PropertyCount] = (SCHEMA_PROPERTY_HANDLE)newProperty;
02035                         structType->PropertyCount++;
02036 
02037                         /* Codes_SRS_SCHEMA_99_071:[On success, Schema_AddStructTypeProperty shall return SCHEMA_OK.] */
02038                         result = SCHEMA_OK;
02039                     }
02040                 }
02041 
02042                 /* If possible, reduce the memory of over allocation */
02043                 if (result != SCHEMA_OK)
02044                 {
02045                     if (structType->PropertyCount > 0)
02046                     {
02047                         SCHEMA_PROPERTY_HANDLE *oldProperties = (SCHEMA_PROPERTY_HANDLE *)realloc(structType->Properties, sizeof(SCHEMA_PROPERTY_HANDLE) * structType->PropertyCount);
02048                         if (oldProperties == NULL)
02049                         {
02050                             result = SCHEMA_ERROR;
02051                             LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02052                         }
02053                         else
02054                         {
02055                             structType->Properties = oldProperties;
02056                         }
02057                     }
02058                     else
02059                     {
02060                         structType->Properties = NULL;
02061                     }
02062                 }
02063             }
02064         }
02065     }
02066 
02067     return result;
02068 }
02069 
02070 SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByName(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, const char* propertyName)
02071 {
02072     SCHEMA_PROPERTY_HANDLE result;
02073 
02074     /* 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.] */
02075     if ((structTypeHandle == NULL) ||
02076         (propertyName == NULL))
02077     {
02078         result = NULL;
02079         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
02080     }
02081     else
02082     {
02083         size_t i;
02084         SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
02085 
02086         for (i = 0; i < structType->PropertyCount; i++)
02087         {
02088             SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)structType->Properties[i];
02089             if (strcmp(modelProperty->PropertyName, propertyName) == 0)
02090             {
02091                 break;
02092             }
02093         }
02094 
02095         /* 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.] */
02096         if (i == structType->PropertyCount)
02097         {
02098             result = NULL;
02099             LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_ELEMENT_NOT_FOUND));
02100         }
02101         /* Codes_SRS_SCHEMA_99_075:[Schema_GetStructTypePropertyByName shall return a non-NULL handle corresponding to a property identified by the structTypeHandle and propertyName.] */
02102         else
02103         {
02104             result = structType->Properties[i];
02105         }
02106     }
02107 
02108     return result;
02109 }
02110 
02111 SCHEMA_RESULT Schema_GetStructTypePropertyCount(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t* propertyCount)
02112 {
02113     SCHEMA_RESULT result;
02114 
02115     /* Codes_SRS_SCHEMA_99_079: [Schema_GetStructTypePropertyCount shall return SCHEMA_INVALID_ARG if any of the structlTypeHandle or propertyCount arguments is NULL.] */
02116     if ((structTypeHandle == NULL) ||
02117         (propertyCount == NULL))
02118     {
02119         result = SCHEMA_INVALID_ARG;
02120         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02121     }
02122     else
02123     {
02124         SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
02125 
02126         /* 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.] */
02127         /* Codes_SRS_SCHEMA_99_081: [The count shall be provided via the out argument propertyCount.] */
02128         *propertyCount = structType->PropertyCount;
02129 
02130         /* Codes_SRS_SCHEMA_99_078: [On success, Schema_ GetStructTypePropertyCount shall return SCHEMA_OK.] */
02131         result = SCHEMA_OK;
02132     }
02133 
02134     return result;
02135 }
02136 
02137 SCHEMA_PROPERTY_HANDLE Schema_GetStructTypePropertyByIndex(SCHEMA_STRUCT_TYPE_HANDLE structTypeHandle, size_t index)
02138 {
02139     SCHEMA_PROPERTY_HANDLE result;
02140     SCHEMA_STRUCT_TYPE_HANDLE_DATA* structType = (SCHEMA_STRUCT_TYPE_HANDLE_DATA*)structTypeHandle;
02141 
02142     /* Codes_SRS_SCHEMA_99_083: [Schema_ GetStructTypeProperty shall return NULL if the index specified is outside the valid range, if structTypeHandle argument is NULL] */
02143     if ((structTypeHandle == NULL) ||
02144         (index >= structType->PropertyCount))
02145     {
02146         result = NULL;
02147         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
02148     }
02149     else
02150     {
02151         /* 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.] */
02152         /* 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.] */
02153         result = structType->Properties[index];
02154     }
02155 
02156     return result;
02157 }
02158 
02159 const char* Schema_GetPropertyName(SCHEMA_PROPERTY_HANDLE propertyHandle)
02160 {
02161     const char* result;
02162 
02163     /* Codes_SRS_SCHEMA_99_086: [If propertyHandle is NULL, Schema_GetPropertyName shall return NULL.] */
02164     if (propertyHandle == NULL)
02165     {
02166         result = NULL;
02167         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
02168     }
02169     else
02170     {
02171         SCHEMA_PROPERTY_HANDLE_DATA* propertyType = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
02172 
02173         /* Codes_SRS_SCHEMA_99_085: [Schema_GetPropertyName shall return the property name identified by the propertyHandle.] */
02174         result = propertyType->PropertyName;
02175     }
02176 
02177     return result;
02178 }
02179 
02180 const char* Schema_GetPropertyType(SCHEMA_PROPERTY_HANDLE propertyHandle)
02181 {
02182     const char* result;
02183 
02184     /* Codes_SRS_SCHEMA_99_088: [If propertyHandle is NULL, Schema_GetPropertyType shall return NULL.] */
02185     if (propertyHandle == NULL)
02186     {
02187         result = NULL;
02188         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
02189     }
02190     else
02191     {
02192         SCHEMA_PROPERTY_HANDLE_DATA* modelProperty = (SCHEMA_PROPERTY_HANDLE_DATA*)propertyHandle;
02193 
02194         /* Codes_SRS_SCHEMA_99_087: [Schema_GetPropertyType shall return the property type identified by the propertyHandle.] */
02195         result = modelProperty->PropertyType;
02196     }
02197 
02198     return result;
02199 }
02200 
02201 SCHEMA_RESULT Schema_GetModelCount(SCHEMA_HANDLE schemaHandle, size_t* modelCount)
02202 {
02203     SCHEMA_RESULT result;
02204     /* Codes_SRS_SCHEMA_99_123: [Schema_GetModelCount shall return SCHEMA_INVALID_ARG if any of the arguments is NULL.] */
02205     if ((schemaHandle == NULL) ||
02206         (modelCount == NULL) )
02207     {
02208         result = SCHEMA_INVALID_ARG;
02209         LogError("(result = %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02210     }
02211     else
02212     {
02213         /* Codes_SRS_SCHEMA_99_120: [Schema_GetModelCount shall provide the number of models defined in the schema identified by schemaHandle.] */
02214         SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
02215         /* Codes_SRS_SCHEMA_99_121: [The count shall be provided via the out argument modelCount.] */
02216         *modelCount = schema->ModelTypeCount;
02217         /* Codes_SRS_SCHEMA_99_122: [On success, Schema_GetModelCount shall return SCHEMA_OK.] */
02218         result = SCHEMA_OK;
02219     }
02220     return result;
02221 }
02222 
02223 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByName(SCHEMA_HANDLE schemaHandle, const char* modelName)
02224 {
02225     SCHEMA_MODEL_TYPE_HANDLE result;
02226 
02227     /* 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.] */
02228     if ((schemaHandle == NULL) ||
02229         (modelName == NULL))
02230     {
02231         result = NULL;
02232         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
02233     }
02234     else
02235     {
02236         /* 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.] */
02237         SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
02238         size_t i;
02239         for (i = 0; i < schema->ModelTypeCount; i++)
02240         {
02241             SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)schema->ModelTypes[i];
02242             if (strcmp(modelName, modelType->Name)==0)
02243             {
02244                 break;
02245             }
02246         }
02247         if (i == schema->ModelTypeCount)
02248         {
02249             /* 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.] */
02250             result = NULL;
02251         }
02252         else
02253         {
02254             result = schema->ModelTypes[i];
02255         }
02256     }
02257     return result;
02258 }
02259 
02260 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelByIndex(SCHEMA_HANDLE schemaHandle, size_t index)
02261 {
02262     SCHEMA_MODEL_TYPE_HANDLE result;
02263     SCHEMA_HANDLE_DATA* schema = (SCHEMA_HANDLE_DATA*)schemaHandle;
02264 
02265     /* 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.] */
02266     /* 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.] */
02267     if ((schemaHandle == NULL) ||
02268         (index >= schema->ModelTypeCount))
02269     {
02270         result = NULL;
02271         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
02272     }
02273     else
02274     {
02275 
02276         /* 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.] */
02277         /* 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.] */
02278         result = schema->ModelTypes[index];
02279     }
02280     return result;
02281 }
02282 
02283 /*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.]*/
02284 const char* Schema_GetModelName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle)
02285 {
02286     const char* result;
02287     if (modelTypeHandle == NULL)
02288     {
02289         result = NULL;
02290     }
02291     else
02292     {
02293         SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02294         result = modelType->Name;
02295     }
02296     return result;
02297 }
02298 
02299 /*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.]*/
02300 SCHEMA_RESULT Schema_AddModelModel(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName, SCHEMA_MODEL_TYPE_HANDLE modelType, size_t offset, pfOnDesiredProperty onDesiredProperty)
02301 {
02302     SCHEMA_RESULT result;
02303     /*Codes_SRS_SCHEMA_99_165: [If any of the parameters is NULL then Schema_AddModelModel shall return SCHEMA_INVALID_ARG.]*/
02304     if (
02305         (modelTypeHandle == NULL) ||
02306         (propertyName == NULL) ||
02307         (modelType == NULL)
02308         )
02309     {
02310         result = SCHEMA_INVALID_ARG;
02311         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, SCHEMA_INVALID_ARG));
02312     }
02313     else
02314     {
02315         SCHEMA_MODEL_TYPE_HANDLE_DATA* parentModel = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02316         MODEL_IN_MODEL temp;
02317         temp.modelHandle = modelType;
02318         temp.offset = offset;
02319         temp.onDesiredProperty = onDesiredProperty;
02320         if (mallocAndStrcpy_s((char**)&(temp.propertyName), propertyName) != 0)
02321         {
02322             result = SCHEMA_ERROR;
02323             LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02324         }
02325         else if (VECTOR_push_back(parentModel->models, &temp, 1) != 0)
02326         {
02327             /*Codes_SRS_SCHEMA_99_174: [The function shall return SCHEMA_ERROR if any other error occurs.]*/
02328             free((void*)temp.propertyName);
02329             result = SCHEMA_ERROR;
02330             LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02331         }
02332         else
02333         {
02334             /*Codes_SRS_SCHEMA_99_164: [If the function succeeds, then the return value shall be SCHEMA_OK.]*/
02335 
02336             result = SCHEMA_OK;
02337         }
02338     }
02339     return result;
02340 }
02341 
02342 
02343 SCHEMA_RESULT Schema_GetModelModelCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* modelCount)
02344 {
02345     SCHEMA_RESULT result;
02346     /*Codes_SRS_SCHEMA_99_169: [If any of the parameters is NULL, then the function shall return SCHEMA_INVALID_ARG.]*/
02347     if (
02348         (modelTypeHandle == NULL) ||
02349         (modelCount == NULL)
02350         )
02351     {
02352         result = SCHEMA_INVALID_ARG;
02353         LogError("(Error code: %s)", ENUM_TO_STRING(SCHEMA_RESULT, result));
02354     }
02355     else
02356     {
02357         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02358         /*Codes_SRS_SCHEMA_99_167: [Schema_GetModelModelCount shall return in parameter modelCount the number of models inserted in the model identified by parameter modelTypeHandle.]*/
02359         *modelCount = VECTOR_size(model->models);
02360         /*SRS_SCHEMA_99_168: [If the function succeeds, it shall return SCHEMA_OK.]*/
02361         result = SCHEMA_OK;
02362     }
02363     return result;
02364 }
02365 
02366 static bool matchModelName(const void* element, const void* value)
02367 {
02368     MODEL_IN_MODEL* decodedElement = (MODEL_IN_MODEL*)element;
02369     const char* name = (const char*)value;
02370     return (strcmp(decodedElement->propertyName, name) == 0);
02371 }
02372 
02373 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
02374 {
02375     SCHEMA_MODEL_TYPE_HANDLE result;
02376     if (
02377         (modelTypeHandle == NULL) ||
02378         (propertyName == NULL)
02379         )
02380     {
02381         /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
02382         result = NULL;
02383         LogError("error SCHEMA_INVALID_ARG");
02384     }
02385     else
02386     {
02387         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02388         /*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.]*/
02389         /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
02390         void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
02391         if (temp == NULL)
02392         {
02393             LogError("specified propertyName not found (%s)", propertyName);
02394             result = NULL;
02395         }
02396         else
02397         {
02398             result = ((MODEL_IN_MODEL*)temp)->modelHandle;
02399         }
02400     }
02401     return result;
02402 }
02403 
02404 size_t Schema_GetModelModelByName_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
02405 {
02406     size_t result;
02407     /*Codes_SRS_SCHEMA_02_053: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
02408     /*Codes_SRS_SCHEMA_02_054: [ If propertyName is NULL then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
02409     if (
02410         (modelTypeHandle == NULL) ||
02411         (propertyName == NULL)
02412         )
02413     {
02414         /*Codes_SRS_SCHEMA_99_171: [If Schema_GetModelModelByName is unable to provide the handle it shall return NULL.]*/
02415         result = 0;
02416         LogError("error SCHEMA_INVALID_ARG");
02417     }
02418     else
02419     {
02420         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02421         /*Codes_SRS_SCHEMA_02_056: [ If propertyName is not a model then Schema_GetModelModelByName_Offset shall fail and return 0. ]*/
02422         void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
02423         if (temp == NULL)
02424         {
02425             LogError("specified propertyName not found (%s)", propertyName);
02426             result = 0;
02427         }
02428         else
02429         {
02430             /*Codes_SRS_SCHEMA_02_055: [ Otherwise Schema_GetModelModelByName_Offset shall succeed and return the offset. ]*/
02431             result = ((MODEL_IN_MODEL*)temp)->offset;
02432         }
02433     }
02434     return result;
02435 }
02436 
02437 pfOnDesiredProperty Schema_GetModelModelByName_OnDesiredProperty(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyName)
02438 {
02439     pfOnDesiredProperty result;
02440     /*Codes_SRS_SCHEMA_02_086: [ If modelTypeHandle is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/
02441     /*Codes_SRS_SCHEMA_02_087: [ If propertyName is NULL then Schema_GetModelModelByName_OnDesiredProperty shall return NULL. ]*/
02442     if (
02443         (modelTypeHandle == NULL) ||
02444         (propertyName == NULL)
02445         )
02446     {
02447         result = NULL;
02448         LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* propertyName=%p",modelTypeHandle, propertyName);
02449     }
02450     else
02451     {
02452         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02453         void* temp = VECTOR_find_if(model->models, matchModelName, propertyName);
02454         if (temp == NULL)
02455         {
02456             LogError("specified propertyName not found (%s)", propertyName);
02457             result = NULL;
02458         }
02459         else
02460         {
02461             /*Codes_SRS_SCHEMA_02_089: [ Otherwise Schema_GetModelModelByName_OnDesiredProperty shall return the desired property callback. ]*/
02462             result = ((MODEL_IN_MODEL*)temp)->onDesiredProperty;
02463         }
02464     }
02465     return result;
02466 
02467 }
02468 
02469 size_t Schema_GetModelModelByIndex_Offset(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
02470 {
02471     size_t result;
02472     /*Codes_SRS_SCHEMA_02_057: [ If modelTypeHandle is NULL then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/
02473     if (modelTypeHandle == NULL)
02474     {
02475         result = 0;
02476         LogError("error SCHEMA_INVALID_ARG");
02477     }
02478     else
02479     {
02480         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02481         /*Codes_SRS_SCHEMA_02_058: [ If index is not valid then Schema_GetModelModelByIndex_Offset shall fail and return 0. ]*/
02482         void* temp = VECTOR_element(model->models, index);
02483         if (temp == 0)
02484         {
02485             LogError("specified index [out of bounds] (%zu)", index);
02486             result = 0;
02487         }
02488         else
02489         {
02490             /*Codes_SRS_SCHEMA_02_059: [ Otherwise Schema_GetModelModelByIndex_Offset shall succeed and return the offset. ]*/
02491             result = ((MODEL_IN_MODEL*)temp)->offset;
02492         }
02493     }
02494     return result;
02495 }
02496 
02497 SCHEMA_MODEL_TYPE_HANDLE Schema_GetModelModelyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
02498 {
02499     SCHEMA_MODEL_TYPE_HANDLE result;
02500     if (modelTypeHandle == NULL)
02501     {
02502         /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/
02503         result = NULL;
02504         LogError("error SCHEMA_INVALID_ARG");
02505     }
02506     else
02507     {
02508         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02509         size_t nModelsInModel;
02510         /*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.]*/
02511         /*Codes_SRS_SCHEMA_99_173: [Schema_GetModelModelyByIndex shall return NULL in the cases when it cannot provide the handle.]*/
02512         nModelsInModel = VECTOR_size(model->models);
02513         if (index < nModelsInModel)
02514         {
02515             result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->modelHandle;
02516         }
02517         else
02518         {
02519             LogError("attempted out of bounds access in array.");
02520             result = NULL; /*out of bounds array access*/
02521         }
02522     }
02523     return result;
02524 }
02525 
02526 const char* Schema_GetModelModelPropertyNameByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
02527 {
02528     const char* result;
02529     if (modelTypeHandle == NULL)
02530     {
02531         /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/
02532         result = NULL;
02533     }
02534     else
02535     {
02536         SCHEMA_MODEL_TYPE_HANDLE_DATA* model = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02537         size_t nModelsInModel;
02538         /*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.]*/
02539         /*Codes_SRS_SCHEMA_99_176: [If Schema_GetModelModelPropertyNameByIndex cannot produce the property name, it shall return NULL.]*/
02540         nModelsInModel = VECTOR_size(model->models);
02541         if (index < nModelsInModel)
02542         {
02543             result = ((MODEL_IN_MODEL*)VECTOR_element(model->models, index))->propertyName;
02544         }
02545         else
02546         {
02547             LogError("attempted out of bounds access in array.");
02548             result = NULL; /*out of bounds array access*/
02549         }
02550     }
02551     return result;
02552 }
02553 
02554 bool Schema_ModelPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* propertyPath)
02555 {
02556     bool result;
02557 
02558     /* Codes_SRS_SCHEMA_99_180: [If any of the arguments are NULL, Schema_ModelPropertyByPathExists shall return false.] */
02559     if ((modelTypeHandle == NULL) ||
02560         (propertyPath == NULL))
02561     {
02562         LogError("error SCHEMA_INVALID_ARG");
02563         result = false;
02564     }
02565     else
02566     {
02567         const char* slashPos;
02568         result = false;
02569 
02570         /* Codes_SRS_SCHEMA_99_182: [A single slash ('/') at the beginning of the path shall be ignored and the path shall still be valid.] */
02571         if (*propertyPath == '/')
02572         {
02573             propertyPath++;
02574         }
02575 
02576         do
02577         {
02578             const char* endPos;
02579             size_t i;
02580             size_t modelCount;
02581             SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02582 
02583             /* Codes_SRS_SCHEMA_99_179: [The propertyPath shall be assumed to be in the format model1/model2/.../propertyName.] */
02584             slashPos = strchr(propertyPath, '/');
02585             endPos = slashPos;
02586             if (endPos == NULL)
02587             {
02588                 endPos = &propertyPath[strlen(propertyPath)];
02589             }
02590 
02591             /* get the child-model */
02592             modelCount = VECTOR_size(modelType->models);
02593             for (i = 0; i < modelCount; i++)
02594             {
02595                 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
02596                 if ((strncmp(childModel->propertyName, propertyPath, endPos - propertyPath) == 0) &&
02597                     (strlen(childModel->propertyName) == (size_t)(endPos - propertyPath)))
02598                 {
02599                     /* found */
02600                     modelTypeHandle = childModel->modelHandle;
02601                     break;
02602                 }
02603             }
02604 
02605             if (i < modelCount)
02606             {
02607                 /* model found, check if there is more in the path */
02608                 if (slashPos == NULL)
02609                 {
02610                     /* this is the last one, so this is the thing we were looking for */
02611                     result = true;
02612                     break;
02613                 }
02614                 else
02615                 {
02616                     /* continue looking, there's more  */
02617                     propertyPath = slashPos + 1;
02618                 }
02619             }
02620             else
02621             {
02622                 /* no model found, let's see if this is a property */
02623                 /* Codes_SRS_SCHEMA_99_178: [The argument propertyPath shall be used to find the leaf property.] */
02624                 for (i = 0; i < modelType->PropertyCount; i++)
02625                 {
02626                     SCHEMA_PROPERTY_HANDLE_DATA* property = (SCHEMA_PROPERTY_HANDLE_DATA*)modelType->Properties[i];
02627                     if ((strncmp(property->PropertyName, propertyPath, endPos - propertyPath) == 0) &&
02628                         (strlen(property->PropertyName) == (size_t)(endPos - propertyPath)))
02629                     {
02630                         /* found property */
02631                         /* Codes_SRS_SCHEMA_99_177: [Schema_ModelPropertyByPathExists shall return true if a leaf property exists in the model modelTypeHandle.] */
02632                         result = true;
02633                         break;
02634                     }
02635                 }
02636 
02637                 break;
02638             }
02639         } while (slashPos != NULL);
02640     }
02641 
02642     return result;
02643 }
02644 
02645 bool Schema_ModelReportedPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* reportedPropertyPath)
02646 {
02647     bool result;
02648 
02649     /*Codes_SRS_SCHEMA_02_018: [ If argument modelTypeHandle is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
02650     /*Codes_SRS_SCHEMA_02_019: [ If argument reportedPropertyPath is NULL then Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
02651     if ((modelTypeHandle == NULL) ||
02652         (reportedPropertyPath == NULL))
02653     {
02654         LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* reportedPropertyPath=%s", modelTypeHandle, reportedPropertyPath);
02655         result = false;
02656     }
02657     else
02658     {
02659         const char* slashPos;
02660 
02661         /*Codes_SRS_SCHEMA_02_021: [ If the reported property cannot be found Schema_ModelReportedPropertyByPathExists shall fail and return false. ]*/
02662         result = false;
02663 
02664         /*Codes_SRS_SCHEMA_02_020: [ reportedPropertyPath shall be assumed to be in the format model1/model2/.../reportedPropertyName. ]*/
02665         if (*reportedPropertyPath == '/')
02666         {
02667             reportedPropertyPath++;
02668         }
02669 
02670         do
02671         {
02672             const char* endPos;
02673             size_t i;
02674             size_t modelCount;
02675             SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02676 
02677             slashPos = strchr(reportedPropertyPath, '/');
02678             endPos = slashPos;
02679             if (endPos == NULL)
02680             {
02681                 endPos = &reportedPropertyPath[strlen(reportedPropertyPath)];
02682             }
02683 
02684             modelCount = VECTOR_size(modelType->models);
02685             for (i = 0; i < modelCount; i++)
02686             {
02687                 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
02688                 if ((strncmp(childModel->propertyName, reportedPropertyPath, endPos - reportedPropertyPath) == 0) &&
02689                     (strlen(childModel->propertyName) == (size_t)(endPos - reportedPropertyPath)))
02690                 {
02691                     /* found */
02692                     modelTypeHandle = childModel->modelHandle;
02693                     break;
02694                 }
02695             }
02696 
02697             if (i < modelCount)
02698             {
02699                 /* model found, check if there is more in the path */
02700                 if (slashPos == NULL)
02701                 {
02702                     /*Codes_SRS_SCHEMA_02_022: [ If the path reportedPropertyPath points to a sub-model, Schema_ModelReportedPropertyByPathExists shall succeed and true. ]*/
02703                     /* this is the last one, so this is the thing we were looking for */
02704                     result = true;
02705                     break;
02706                 }
02707                 else
02708                 {
02709                     /* continue looking, there's more  */
02710                     reportedPropertyPath = slashPos + 1;
02711                 }
02712             }
02713             else
02714             {
02715                 /* no model found, let's see if this is a property */
02716                 result = (VECTOR_find_if(modelType->reportedProperties, reportedPropertyExists, reportedPropertyPath) != NULL);
02717                 if (!result)
02718                 {
02719                     LogError("no such reported property \"%s\"", reportedPropertyPath);
02720                 }
02721                 break;
02722             }
02723         } while (slashPos != NULL);
02724     }
02725 
02726     return result;
02727 }
02728 
02729 static bool desiredPropertyExists(const void* element, const void* value)
02730 {
02731     SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = *(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA**)element;
02732     return (strcmp(desiredProperty->desiredPropertyName, value) == 0);
02733 }
02734 
02735 SCHEMA_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)
02736 {
02737     SCHEMA_RESULT result;
02738     /*Codes_SRS_SCHEMA_02_024: [ If modelTypeHandle is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
02739     /*Codes_SRS_SCHEMA_02_025: [ If desiredPropertyName is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
02740     /*Codes_SRS_SCHEMA_02_026: [ If desiredPropertyType is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
02741     /*Codes_SRS_SCHEMA_02_048: [ If desiredPropertyFromAGENT_DATA_TYPE is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
02742     /*Codes_SRS_SCHEMA_02_049: [ If desiredPropertyInitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
02743     /*Codes_SRS_SCHEMA_02_050: [ If desiredPropertyDeinitialize is NULL then Schema_AddModelDesiredProperty shall fail and return SCHEMA_INVALID_ARG. ]*/
02744     if (
02745         (modelTypeHandle == NULL) ||
02746         (desiredPropertyName == NULL) ||
02747         (desiredPropertyType == NULL) ||
02748         (desiredPropertyFromAGENT_DATA_TYPE == NULL) ||
02749         (desiredPropertyInitialize == NULL) ||
02750         (desiredPropertyDeinitialize== NULL)
02751         )
02752     {
02753         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=%zu",
02754             modelTypeHandle, desiredPropertyName, desiredPropertyType, desiredPropertyFromAGENT_DATA_TYPE, desiredPropertyInitialize, desiredPropertyDeinitialize, offset);
02755         result = SCHEMA_INVALID_ARG;
02756     }
02757     else
02758     {
02759         SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02760         /*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. ]*/
02761         if (VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName) != NULL)
02762         {
02763             /*Codes_SRS_SCHEMA_02_047: [ If the desired property already exists, then Schema_AddModelDesiredProperty shall fail and return SCHEMA_DUPLICATE_ELEMENT. ]*/
02764             LogError("unable to Schema_AddModelDesiredProperty because a desired property with the same name (%s) already exists", desiredPropertyName);
02765             result = SCHEMA_DUPLICATE_ELEMENT;
02766         }
02767         else
02768         {
02769             SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desiredProperty = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)malloc(sizeof(SCHEMA_DESIRED_PROPERTY_HANDLE_DATA));
02770             if (desiredProperty == NULL)
02771             {
02772                 /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
02773                 LogError("failure in malloc");
02774                 result = SCHEMA_ERROR;
02775             }
02776             else
02777             {
02778                 if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyName, desiredPropertyName) != 0)
02779                 {
02780                     /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
02781                     LogError("failure in mallocAndStrcpy_s");
02782                     free(desiredProperty);
02783                     result = SCHEMA_ERROR;
02784                 }
02785                 else
02786                 {
02787                     if (mallocAndStrcpy_s((char**)&desiredProperty->desiredPropertyType, desiredPropertyType) != 0)
02788                     {
02789                         /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
02790                         LogError("failure in mallocAndStrcpy_s");
02791                         free((void*)desiredProperty->desiredPropertyName);
02792                         free(desiredProperty);
02793                         result = SCHEMA_ERROR;
02794                     }
02795                     else
02796                     {
02797                         if (VECTOR_push_back(handleData->desiredProperties, &desiredProperty, 1) != 0)
02798                         {
02799                             /*Codes_SRS_SCHEMA_02_028: [ If any failure occurs then Schema_AddModelDesiredProperty shall fail and return SCHEMA_ERROR. ]*/
02800                             LogError("failure in VECTOR_push_back");
02801                             free((void*)desiredProperty->desiredPropertyType);
02802                             free((void*)desiredProperty->desiredPropertyName);
02803                             free(desiredProperty);
02804                             result = SCHEMA_ERROR;
02805                         }
02806                         else
02807                         {
02808                             /*Codes_SRS_SCHEMA_02_029: [ Otherwise, Schema_AddModelDesiredProperty shall succeed and return SCHEMA_OK. ]*/
02809                             desiredProperty->desiredPropertyFromAGENT_DATA_TYPE = desiredPropertyFromAGENT_DATA_TYPE;
02810                             desiredProperty->desiredPropertInitialize = desiredPropertyInitialize;
02811                             desiredProperty->desiredPropertDeinitialize = desiredPropertyDeinitialize;
02812                             desiredProperty->onDesiredProperty = onDesiredProperty; /*NULL is a perfectly fine value*/
02813                             desiredProperty->offset = offset;
02814                             result = SCHEMA_OK;
02815                         }
02816                     }
02817                 }
02818             }
02819         }
02820     }
02821     return result;
02822 }
02823 
02824 
02825 SCHEMA_RESULT Schema_GetModelDesiredPropertyCount(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t* desiredPropertyCount)
02826 {
02827     SCHEMA_RESULT result;
02828     /*Codes_SRS_SCHEMA_02_030: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
02829     /*Codes_SRS_SCHEMA_02_031: [ If desiredPropertyCount is NULL then Schema_GetModelDesiredPropertyCount shall fail and return SCHEMA_INVALID_ARG. ]*/
02830     if (
02831         (modelTypeHandle == NULL) ||
02832         (desiredPropertyCount == NULL)
02833         )
02834     {
02835         LogError("invalid arg: SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t* desiredPropertyCount=%p", modelTypeHandle, desiredPropertyCount);
02836         result = SCHEMA_INVALID_ARG;
02837     }
02838     else
02839     {
02840         /*Codes_SRS_SCHEMA_02_032: [ Otherwise, Schema_GetModelDesiredPropertyCount shall succeed and write in desiredPropertyCount the existing number of desired properties. ]*/
02841         SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02842         *desiredPropertyCount = VECTOR_size(handleData->desiredProperties);
02843         result = SCHEMA_OK;
02844     }
02845     return result;
02846 }
02847 
02848 SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyName)
02849 {
02850     SCHEMA_DESIRED_PROPERTY_HANDLE result;
02851     /*Codes_SRS_SCHEMA_02_034: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
02852     /*Codes_SRS_SCHEMA_02_035: [ If desiredPropertyName is NULL then Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
02853     if (
02854         (modelTypeHandle == NULL) ||
02855         (desiredPropertyName == NULL)
02856         )
02857     {
02858         LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyName=%p", modelTypeHandle, desiredPropertyName);
02859         result = NULL;
02860     }
02861     else
02862     {
02863         /*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. ]*/
02864         /*Codes_SRS_SCHEMA_02_037: [ Otherwise, Schema_GetModelDesiredPropertyByName shall fail and return NULL. ]*/
02865         SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02866         SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, desiredPropertyName);
02867         if (temp == NULL)
02868         {
02869             LogError("no such desired property by name %s", desiredPropertyName);
02870             result = NULL;
02871         }
02872         else
02873         {
02874             result = *temp;
02875         }
02876     }
02877     return result;
02878 }
02879 
02880 SCHEMA_DESIRED_PROPERTY_HANDLE Schema_GetModelDesiredPropertyByIndex(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, size_t index)
02881 {
02882     SCHEMA_DESIRED_PROPERTY_HANDLE result;
02883     /*Codes_SRS_SCHEMA_02_038: [ If modelTypeHandle is NULL then Schema_GetModelDesiredPropertyByIndex shall fail and return NULL. ]*/
02884     if (modelTypeHandle == NULL)
02885     {
02886         LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, size_t index=%p", modelTypeHandle, index);
02887         result = NULL;
02888     }
02889     else
02890     {
02891         SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02892         /*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. ]*/
02893         /*Codes_SRS_SCHEMA_02_040: [ Otherwise, Schema_GetModelDesiredPropertyByIndex shall succeed and return a non-NULL value. ]*/
02894         SCHEMA_DESIRED_PROPERTY_HANDLE* temp = VECTOR_element(handleData->desiredProperties, index);
02895         if (temp == NULL)
02896         {
02897             LogError("VECTOR_element produced NULL (likely out of bounds index)");
02898             result = NULL;
02899         }
02900         else
02901         {
02902             result = *temp;
02903         }
02904     }
02905     return result;
02906 }
02907 
02908 bool Schema_ModelDesiredPropertyByPathExists(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* desiredPropertyPath)
02909 {
02910     bool result;
02911     /*Codes_SRS_SCHEMA_02_041: [ If modelTypeHandle is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
02912     /*Codes_SRS_SCHEMA_02_042: [ If desiredPropertyPath is NULL then Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
02913     if (
02914         (modelTypeHandle == NULL) ||
02915         (desiredPropertyPath == NULL)
02916         )
02917     {
02918         LogError("invalid arg SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* desiredPropertyPath=%p", modelTypeHandle, desiredPropertyPath);
02919         result = false;
02920     }
02921     else
02922     {
02923         const char* slashPos;
02924 
02925         /*Codes_SRS_SCHEMA_02_044: [ If the desired property cannot be found Schema_ModelDesiredPropertyByPathExists shall fail and return false. ]*/
02926         result = false;
02927 
02928         /*Codes_SRS_SCHEMA_02_043: [ desiredPropertyPath shall be assumed to be in the format model1/model2/.../desiredPropertyName. ]*/
02929         if (*desiredPropertyPath == '/')
02930         {
02931             desiredPropertyPath++;
02932         }
02933 
02934         do
02935         {
02936             const char* endPos;
02937             size_t i;
02938             size_t modelCount;
02939             SCHEMA_MODEL_TYPE_HANDLE_DATA* modelType = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
02940 
02941             slashPos = strchr(desiredPropertyPath, '/');
02942             endPos = slashPos;
02943             if (endPos == NULL)
02944             {
02945                 endPos = &desiredPropertyPath[strlen(desiredPropertyPath)];
02946             }
02947 
02948             modelCount = VECTOR_size(modelType->models);
02949             for (i = 0; i < modelCount; i++)
02950             {
02951                 MODEL_IN_MODEL* childModel = (MODEL_IN_MODEL*)VECTOR_element(modelType->models, i);
02952                 if ((strncmp(childModel->propertyName, desiredPropertyPath, endPos - desiredPropertyPath) == 0) &&
02953                     (strlen(childModel->propertyName) == (size_t)(endPos - desiredPropertyPath)))
02954                 {
02955                     /* found */
02956                     modelTypeHandle = childModel->modelHandle;
02957                     break;
02958                 }
02959             }
02960 
02961             if (i < modelCount)
02962             {
02963                 /* model found, check if there is more in the path */
02964                 if (slashPos == NULL)
02965                 {
02966                     /*Codes_SRS_SCHEMA_02_045: [ If the path desiredPropertyPath points to a sub-model, Schema_ModelDesiredPropertyByPathExists shall succeed and true. ]*/
02967                     /* this is the last one, so this is the thing we were looking for */
02968                     result = true;
02969                     break;
02970                 }
02971                 else
02972                 {
02973                     /* continue looking, there's more  */
02974                     desiredPropertyPath = slashPos + 1;
02975                 }
02976             }
02977             else
02978             {
02979                 /* no model found, let's see if this is a property */
02980                 result = (VECTOR_find_if(modelType->desiredProperties, desiredPropertyExists, desiredPropertyPath) != NULL);
02981                 if (!result)
02982                 {
02983                     LogError("no such desired property \"%s\"", desiredPropertyPath);
02984                 }
02985                 break;
02986             }
02987         } while (slashPos != NULL);
02988     }
02989     return result;
02990 }
02991 
02992 const char* Schema_GetModelDesiredPropertyType(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
02993 {
02994     const char* result;
02995     /*Codes_SRS_SCHEMA_02_062: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredPropertyType shall fail and return NULL. ]*/
02996     if (desiredPropertyHandle == NULL)
02997     {
02998         LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
02999         result = NULL;
03000     }
03001     else
03002     {
03003         /*Codes_SRS_SCHEMA_02_063: [ Otherwise, Schema_GetModelDesiredPropertyType shall return the type of the desired property. ]*/
03004         SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
03005         result = desirePropertyHandleData->desiredPropertyType;
03006     }
03007     return result;
03008 }
03009 
03010 pfDesiredPropertyFromAGENT_DATA_TYPE Schema_GetModelDesiredProperty_pfDesiredPropertyFromAGENT_DATA_TYPE(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
03011 {
03012     pfDesiredPropertyFromAGENT_DATA_TYPE result;
03013     if (desiredPropertyHandle == NULL)
03014     {
03015         LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
03016         result = NULL;
03017     }
03018     else
03019     {
03020         SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
03021         result = desirePropertyHandleData->desiredPropertyFromAGENT_DATA_TYPE;
03022     }
03023     return result;
03024 }
03025 
03026 pfOnDesiredProperty Schema_GetModelDesiredProperty_pfOnDesiredProperty(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
03027 {
03028     pfOnDesiredProperty result;
03029     /*Codes_SRS_SCHEMA_02_084: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return NULL. ]*/
03030     if (desiredPropertyHandle == NULL)
03031     {
03032         LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
03033         result = NULL;
03034     }
03035     else
03036     {
03037         /*Codes_SRS_SCHEMA_02_085: [ Otherwise Schema_GetModelDesiredProperty_pfOnDesiredProperty shall return the saved desired property callback. ]*/
03038         SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
03039         result = desirePropertyHandleData->onDesiredProperty;
03040     }
03041     return result;
03042 }
03043 
03044 size_t Schema_GetModelDesiredProperty_offset(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
03045 {
03046     size_t result;
03047     /*Codes_SRS_SCHEMA_02_060: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_offset shall fail and return 0. ]*/
03048     if (desiredPropertyHandle == NULL)
03049     {
03050         LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
03051         result = 0;
03052     }
03053     else
03054     {
03055         /*Codes_SRS_SCHEMA_02_061: [ Otherwise Schema_GetModelDesiredProperty_offset shall succeed and return the offset. ]*/
03056         SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* desirePropertyHandleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
03057         result = desirePropertyHandleData->offset;
03058     }
03059     return result;
03060 }
03061 
03062 static bool modelInModelExists(const void* element, const void* value)
03063 {
03064     MODEL_IN_MODEL* modelInModel = (MODEL_IN_MODEL*)element;
03065     return (strcmp(modelInModel->propertyName, value) == 0);
03066 }
03067 
03068 SCHEMA_MODEL_ELEMENT Schema_GetModelElementByName(SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle, const char* elementName)
03069 {
03070     SCHEMA_MODEL_ELEMENT result;
03071     /*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. ]*/
03072     /*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. ]*/
03073     if (
03074         (modelTypeHandle == NULL) ||
03075         (elementName == NULL)
03076         )
03077     {
03078         LogError("invalid argument SCHEMA_MODEL_TYPE_HANDLE modelTypeHandle=%p, const char* elementName=%p", modelTypeHandle, elementName);
03079         result.elementType = SCHEMA_SEARCH_INVALID_ARG;
03080     }
03081     else
03082     {
03083         SCHEMA_MODEL_TYPE_HANDLE_DATA* handleData = (SCHEMA_MODEL_TYPE_HANDLE_DATA*)modelTypeHandle;
03084 
03085         SCHEMA_DESIRED_PROPERTY_HANDLE* desiredPropertyHandle = VECTOR_find_if(handleData->desiredProperties, desiredPropertyExists, elementName);
03086         if (desiredPropertyHandle != NULL)
03087         {
03088             /*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. ]*/
03089             result.elementType = SCHEMA_DESIRED_PROPERTY;
03090             result.elementHandle.desiredPropertyHandle = *desiredPropertyHandle;
03091         }
03092         else
03093         {
03094             size_t nProcessedProperties = 0;
03095             SCHEMA_PROPERTY_HANDLE_DATA* property = NULL;
03096             for (size_t i = 0; i < handleData->PropertyCount;i++)
03097             {
03098                 property = (SCHEMA_PROPERTY_HANDLE_DATA*)(handleData->Properties[i]);
03099                 if (strcmp(property->PropertyName, elementName) == 0)
03100                 {
03101                     i = handleData->PropertyCount; /*found it*/
03102                 }
03103                 else
03104                 {
03105                     nProcessedProperties++;
03106                 }
03107             }
03108 
03109             if (nProcessedProperties < handleData->PropertyCount)
03110             {
03111                 /*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. ]*/
03112                 result.elementType = SCHEMA_PROPERTY;
03113                 result.elementHandle.propertyHandle = property;
03114             }
03115             else
03116             {
03117 
03118                 SCHEMA_REPORTED_PROPERTY_HANDLE* reportedPropertyHandle = VECTOR_find_if(handleData->reportedProperties, reportedPropertyExists, elementName);
03119                 if (reportedPropertyHandle != NULL)
03120                 {
03121                     /*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. ]*/
03122                     result.elementType = SCHEMA_REPORTED_PROPERTY;
03123                     result.elementHandle.reportedPropertyHandle = *reportedPropertyHandle;
03124                 }
03125                 else
03126                 {
03127 
03128                     size_t nProcessedActions = 0;
03129                     SCHEMA_ACTION_HANDLE_DATA* actionHandleData = NULL;
03130                     for (size_t i = 0;i < handleData->ActionCount; i++)
03131                     {
03132                         actionHandleData = (SCHEMA_ACTION_HANDLE_DATA*)(handleData->Actions[i]);
03133                         if (strcmp(actionHandleData->ActionName, elementName) == 0)
03134                         {
03135                             i = handleData->ActionCount; /*get out quickly*/
03136                         }
03137                         else
03138                         {
03139                             nProcessedActions++;
03140                         }
03141                     }
03142 
03143                     if (nProcessedActions < handleData->ActionCount)
03144                     {
03145                         /*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. ]*/
03146                         result.elementType = SCHEMA_MODEL_ACTION;
03147                         result.elementHandle.actionHandle = actionHandleData;
03148                     }
03149                     else
03150                     {
03151                         MODEL_IN_MODEL* modelInModel = VECTOR_find_if(handleData->models, modelInModelExists, elementName);
03152                         if (modelInModel != NULL)
03153                         {
03154                             /*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. ]*/
03155                             result.elementType = SCHEMA_MODEL_IN_MODEL;
03156                             result.elementHandle.modelHandle = modelInModel->modelHandle;
03157                         }
03158                         else
03159                         {
03160                             /*Codes_SRS_SCHEMA_02_083: [ Otherwise Schema_GetModelElementByName shall fail and set SCHEMA_MODEL_ELEMENT.elementType to SCHEMA_NOT_FOUND. ]*/
03161                             result.elementType = SCHEMA_NOT_FOUND;
03162                         }
03163                     }
03164                 }
03165             }
03166         }
03167     }
03168     return result;
03169 }
03170 
03171 pfDesiredPropertyDeinitialize Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
03172 {
03173     pfDesiredPropertyDeinitialize result;
03174     /*Ccodes_SRS_SCHEMA_02_064: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall fail and return NULL. ]*/
03175     if (desiredPropertyHandle == NULL)
03176     {
03177         LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
03178         result = NULL;
03179     }
03180     else
03181     {
03182         /*Codes_SRS_SCHEMA_02_065: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyDeinitialize shall return a non-NULL function pointer. ]*/
03183         SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
03184         result = handleData->desiredPropertDeinitialize;
03185     }
03186     return result;
03187 }
03188 
03189 pfDesiredPropertyInitialize Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize(SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle)
03190 {
03191     pfDesiredPropertyInitialize result;
03192     /*Codes_SRS_SCHEMA_02_066: [ If desiredPropertyHandle is NULL then Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall fail and return NULL. ]*/
03193     if (desiredPropertyHandle == NULL)
03194     {
03195         LogError("invalid argument SCHEMA_DESIRED_PROPERTY_HANDLE desiredPropertyHandle=%p", desiredPropertyHandle);
03196         result = NULL;
03197     }
03198     else
03199     {
03200         /*Codes_SRS_SCHEMA_02_067: [ Otherwise Schema_GetModelDesiredProperty_pfDesiredPropertyInitialize shall return a non-NULL function pointer. ]*/
03201         SCHEMA_DESIRED_PROPERTY_HANDLE_DATA* handleData = (SCHEMA_DESIRED_PROPERTY_HANDLE_DATA*)desiredPropertyHandle;
03202         result = handleData->desiredPropertInitialize;
03203     }
03204     return result;
03205 }
03206 
03207 static bool SchemaHasModel(const SCHEMA_HANDLE* schemaHandle, const char* modelName)
03208 {
03209     return (Schema_GetModelByName(*schemaHandle, modelName) != NULL);
03210 }
03211 
03212 
03213 SCHEMA_HANDLE Schema_GetSchemaForModel(const char* modelName)
03214 {
03215     SCHEMA_HANDLE result;
03216     /*Codes_SRS_SCHEMA_02_093: [ If modelName is NULL then Schema_GetSchemaForModel shall fail and return NULL. ]*/
03217     if (modelName == NULL)
03218     {
03219         LogError("invalid arg const char* modelName=%p", modelName);
03220         result = NULL;
03221     }
03222     else
03223     {
03224         /*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. ]*/
03225         SCHEMA_HANDLE* temp = VECTOR_find_if(g_schemas, (PREDICATE_FUNCTION)SchemaHasModel, modelName);
03226 
03227         if (temp == NULL)
03228         {
03229             /*Codes_SRS_SCHEMA_02_095: [ If the model is not found in any schema, then Schema_GetSchemaForModel shall fail and return NULL. ]*/
03230             LogError("unable to find a schema that has a model named %s", modelName);
03231             result = NULL;
03232         }
03233         else
03234         {
03235             /*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. ]*/
03236             result = *temp;
03237         }
03238     }
03239 
03240     return result;
03241 }
03242 
03243 void* Schema_GetMetadata(SCHEMA_HANDLE schemaHandle)
03244 {
03245     void* result;
03246     /*Codes_SRS_SCHEMA_02_091: [ If schemaHandle is NULL then Schema_GetMetadata shall fail and return NULL. ]*/
03247     if (schemaHandle == NULL)
03248     {
03249         LogError("invalid arg SCHEMA_HANDLE schemaHandle=%p", schemaHandle);
03250         result = NULL;
03251     }
03252     else
03253     {
03254         /*Codes_SRS_SCHEMA_02_092: [ Otherwise, Schema_GetMetadata shall succeed and return the saved metadata pointer. ]*/
03255         result = ((SCHEMA_HANDLE_DATA*)schemaHandle)->metadata;
03256     }
03257     return result;
03258 }