WIP: New XML schemas used in gem-graph
This commit is contained in:
parent
33da3fee8d
commit
b2a3508f08
|
@ -37,6 +37,8 @@
|
||||||
#define LOGMSG "[%s]"
|
#define LOGMSG "[%s]"
|
||||||
#define printLog(FORMAT, ...) printf("\e[0m" LOGMSG " " FORMAT "\e[0m", \
|
#define printLog(FORMAT, ...) printf("\e[0m" LOGMSG " " FORMAT "\e[0m", \
|
||||||
__func__, ##__VA_ARGS__)
|
__func__, ##__VA_ARGS__)
|
||||||
|
#define printErr(FORMAT,...) sprintf(stderr, "\e[0m" LOGMSG " " FORMAT "\e[0m",\
|
||||||
|
__func__, ##__VA_ARGS__)
|
||||||
#define LEN(x) (sizeof(x) / sizeof((x)[0]))
|
#define LEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <libxml/parser.h>
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/xmlschemas.h>
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -66,4 +67,6 @@ int parseTextField(xmlDocPtr,
|
||||||
|
|
||||||
int ParseModelXML(Model_t*);
|
int ParseModelXML(Model_t*);
|
||||||
|
|
||||||
|
int ParseModelIdentityXML(Model_t*, Parameters_t*);
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
68
src/main.c
68
src/main.c
|
@ -44,72 +44,66 @@ int main(int argc, char **argv)
|
||||||
int options;
|
int options;
|
||||||
time_t t;
|
time_t t;
|
||||||
int returnValue = 0;
|
int returnValue = 0;
|
||||||
Parameters_t *parameters;
|
Parameters_t parameters;
|
||||||
|
|
||||||
// Get parameters TODO from args
|
|
||||||
parameters = (Parameters_t*) calloc(sizeof(Parameters_t), 1);
|
|
||||||
|
|
||||||
while ((options = getopt(argc, argv, ":C:M:U:")) != -1) {
|
while ((options = getopt(argc, argv, ":C:M:U:")) != -1) {
|
||||||
switch (options) {
|
switch (options) {
|
||||||
case 'C':
|
case 'C':
|
||||||
printLog("Config : %s\n", optarg);
|
printLog("Config : %s\n", optarg);
|
||||||
parameters->configDir = (char*) malloc(strlen(optarg) + 1);
|
parameters.configDir = (char*) calloc(1, strlen(optarg) + 1);
|
||||||
strcpy(parameters->configDir, optarg);
|
strcpy(parameters.configDir, optarg);
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'M':
|
||||||
printLog("Models : %s\n", optarg);
|
printLog("Models : %s\n", optarg);
|
||||||
parameters->modelDir = (char*) malloc(strlen(optarg) + 1);
|
parameters.modelDir = (char*) calloc(1, strlen(optarg) + 1);
|
||||||
strcpy(parameters->modelDir, optarg);
|
strcpy(parameters.modelDir, optarg);
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
printLog("User : %s\n", optarg);
|
printLog("User : %s\n", optarg);
|
||||||
parameters->userDir = (char*) malloc(strlen(optarg) + 1);
|
parameters.userDir = (char*) calloc(1, strlen(optarg) + 1);
|
||||||
strcpy(parameters->userDir, optarg);
|
strcpy(parameters.userDir, optarg);
|
||||||
break;
|
break;
|
||||||
case ':':
|
case ':':
|
||||||
printLog("Option missing argument : %c\n", optopt);
|
printLog("Option missing argument : %c\n", optopt);
|
||||||
if (parameters->configDir)
|
if (parameters.configDir)
|
||||||
free(parameters->configDir);
|
free(parameters.configDir);
|
||||||
|
|
||||||
if (parameters->modelDir)
|
if (parameters.modelDir)
|
||||||
free(parameters->modelDir);
|
free(parameters.modelDir);
|
||||||
|
|
||||||
if (parameters->userDir)
|
if (parameters.userDir)
|
||||||
free(parameters->userDir);
|
free(parameters.userDir);
|
||||||
|
|
||||||
free(parameters);
|
|
||||||
return ENOSYS;
|
return ENOSYS;
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
printLog("Unknown option : %c\n", optopt);
|
printLog("Unknown option : %c\n", optopt);
|
||||||
if (parameters->configDir)
|
if (parameters.configDir)
|
||||||
free(parameters->configDir);
|
free(parameters.configDir);
|
||||||
|
|
||||||
if (parameters->modelDir)
|
if (parameters.modelDir)
|
||||||
free(parameters->modelDir);
|
free(parameters.modelDir);
|
||||||
|
|
||||||
if (parameters->userDir)
|
if (parameters.userDir)
|
||||||
free(parameters->userDir);
|
free(parameters.userDir);
|
||||||
|
|
||||||
free(parameters);
|
|
||||||
return ENOSYS;
|
return ENOSYS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parameters->configDir | !parameters->modelDir | !parameters->userDir) {
|
if (!parameters.configDir | !parameters.modelDir | !parameters.userDir) {
|
||||||
printLog("Missing arguments\n");
|
printLog("Missing arguments\n");
|
||||||
|
|
||||||
if (parameters->configDir)
|
if (parameters.configDir)
|
||||||
free(parameters->configDir);
|
free(parameters.configDir);
|
||||||
|
|
||||||
if (parameters->modelDir)
|
if (parameters.modelDir)
|
||||||
free(parameters->modelDir);
|
free(parameters.modelDir);
|
||||||
|
|
||||||
if (parameters->userDir)
|
if (parameters.userDir)
|
||||||
free(parameters->userDir);
|
free(parameters.userDir);
|
||||||
|
|
||||||
free(parameters);
|
|
||||||
return ENOSYS;
|
return ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +121,7 @@ int main(int argc, char **argv)
|
||||||
server = (Server_t*) calloc(1, sizeof(Server_t));
|
server = (Server_t*) calloc(1, sizeof(Server_t));
|
||||||
|
|
||||||
// Initializing model system
|
// Initializing model system
|
||||||
ModelSystemInit(parameters);
|
ModelSystemInit(¶meters);
|
||||||
|
|
||||||
// Launching server
|
// Launching server
|
||||||
ServerInit(server);
|
ServerInit(server);
|
||||||
|
@ -141,11 +135,9 @@ int main(int argc, char **argv)
|
||||||
free(server);
|
free(server);
|
||||||
server = NULL;
|
server = NULL;
|
||||||
|
|
||||||
free(parameters->userDir);
|
free(parameters.userDir);
|
||||||
free(parameters->modelDir);
|
free(parameters.modelDir);
|
||||||
free(parameters->configDir);
|
free(parameters.configDir);
|
||||||
free(parameters);
|
|
||||||
parameters = NULL;
|
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,13 +272,17 @@ void ModelSystemInit(Parameters_t *parameters)
|
||||||
extensionPosition - modelDirEntry->d_name);
|
extensionPosition - modelDirEntry->d_name);
|
||||||
|
|
||||||
// Ask to parse the new model
|
// Ask to parse the new model
|
||||||
if (ParseModelXML(newModel) != 0) {
|
if (ParseModelIdentityXML(newModel, parameters) != 0) {
|
||||||
|
printLog("Deleting invalid model %s from known list\n",
|
||||||
|
newModel->name);
|
||||||
ModelDelete(newModel->id);
|
ModelDelete(newModel->id);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check model is valid and/or parsed
|
// Check model is valid and/or parsed
|
||||||
if (newModel->validated == false) {
|
if (newModel->validated == false) {
|
||||||
|
printLog("Deleting invalid model %s from known list\n",
|
||||||
|
newModel->name);
|
||||||
ModelDelete(newModel->id);
|
ModelDelete(newModel->id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
161
src/parsing.c
161
src/parsing.c
|
@ -294,14 +294,22 @@ int parseParentFieldPropsXML (xmlDocPtr doc,
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------- //
|
// -------------------------------------------------------------------------- //
|
||||||
// Parsing a model file //
|
// Preparsing a model file //
|
||||||
// -------------------------------------------------------------------------- //
|
// -------------------------------------------------------------------------- //
|
||||||
int ParseModelXML(Model_t *model)
|
int ParseModelIdentityXML(Model_t *model, Parameters_t *params)
|
||||||
{
|
{
|
||||||
|
xmlDocPtr xmlDocument;
|
||||||
|
xmlNodePtr currentNode;
|
||||||
|
xmlChar *version = NULL;
|
||||||
|
xmlSchemaPtr schemPtr;
|
||||||
|
xmlSchemaValidCtxtPtr schemValidator;
|
||||||
|
xmlSchemaParserCtxtPtr schemFile;
|
||||||
|
char *schemPath;
|
||||||
|
|
||||||
ParserTableXML_t table[] =
|
ParserTableXML_t table[] =
|
||||||
{
|
{
|
||||||
// IDENTITY
|
// IDENTITY
|
||||||
{(const xmlChar *)"identity", parseParentFieldXML, model},
|
{(const xmlChar *)"identity", parseParentFieldXML, NULL},
|
||||||
{(const xmlChar *)"name", parseTextFieldXML, model->name},
|
{(const xmlChar *)"name", parseTextFieldXML, model->name},
|
||||||
{(const xmlChar *)"owner", parseTextFieldXML, model->owner},
|
{(const xmlChar *)"owner", parseTextFieldXML, model->owner},
|
||||||
|
|
||||||
|
@ -309,8 +317,149 @@ int ParseModelXML(Model_t *model)
|
||||||
{(const xmlChar *)"owner_id", parseStubFieldXML, model->owner_id},
|
{(const xmlChar *)"owner_id", parseStubFieldXML, model->owner_id},
|
||||||
|
|
||||||
{(const xmlChar *)"date", parseIntFieldXML, &model->date},
|
{(const xmlChar *)"date", parseIntFieldXML, &model->date},
|
||||||
{(const xmlChar *)"version", parseTextFieldXML, model->version},
|
{(const xmlChar *)"version", parseTextFieldXML, model->version}
|
||||||
|
};
|
||||||
|
|
||||||
|
ModelParserTableXML_t identityParserTable =
|
||||||
|
{
|
||||||
|
LEN(table),
|
||||||
|
&table[0]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allocating space for schema file path
|
||||||
|
schemPath = (char*)calloc(1, strlen(params->modelDir)
|
||||||
|
+ strlen("/schemas/model_x.x.xmls"));
|
||||||
|
|
||||||
|
printLog("Preparsing model %s\n", model->name);
|
||||||
|
|
||||||
|
// Opening document
|
||||||
|
xmlDocument = xmlParseFile(model->filename);
|
||||||
|
|
||||||
|
if (xmlDocument == NULL) {
|
||||||
|
printLog("Can't parse model file at '%s'.\n", model->filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getting root from XML model file
|
||||||
|
currentNode = xmlDocGetRootElement(xmlDocument);
|
||||||
|
|
||||||
|
if (currentNode == NULL) {
|
||||||
|
printLog("Invalid model file at '%s', document empty !\n",
|
||||||
|
model->filename);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking that XML file is actually a model
|
||||||
|
if (xmlStrcmp(currentNode->name, (const xmlChar *) "gem-graph-model")) {
|
||||||
|
printLog("Invalid model file at '%s', "
|
||||||
|
"root node is not <gem-graph-model> !\n",
|
||||||
|
model->filename);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gem-graph model version to parse
|
||||||
|
version = xmlGetProp(currentNode, (xmlChar*)"version");
|
||||||
|
// Check version is present
|
||||||
|
if (!version) {
|
||||||
|
printLog("Missing version for model %s \n", model->name);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
return -4;
|
||||||
|
} else if (strlen((char*)version) > MODEL_STRING_SIZE) {
|
||||||
|
printLog("Invalid version number for model %s \n", model->name);
|
||||||
|
free(version);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
}
|
||||||
|
printLog("Gem-graph model version %s detected\n", version);
|
||||||
|
|
||||||
|
// Retrieving schema file
|
||||||
|
sprintf(schemPath, "%s/schemas/model_%s.xmls", params->modelDir, version);
|
||||||
|
printLog("Loading schema %s\n", schemPath);
|
||||||
|
|
||||||
|
// Loading schema file
|
||||||
|
schemFile = xmlSchemaNewParserCtxt(schemPath);
|
||||||
|
if (schemFile == NULL) {
|
||||||
|
printLog("Invalid gem-graph version %s in model %s: no schema present",
|
||||||
|
version, model->name);
|
||||||
|
free(version);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
return -5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading schema file content
|
||||||
|
schemPtr = xmlSchemaParse(schemFile);
|
||||||
|
xmlSchemaFreeParserCtxt(schemFile);
|
||||||
|
if (schemPtr == NULL) {
|
||||||
|
printLog("Invalid schema file, version %s\n", version);
|
||||||
|
free(version);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating validating context
|
||||||
|
schemValidator = xmlSchemaNewValidCtxt(schemPtr);
|
||||||
|
if (schemValidator == NULL) {
|
||||||
|
xmlSchemaFree(schemPtr);
|
||||||
|
free(version);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
printLog("An error occured preparing schema file, version %s\n", version);
|
||||||
|
return -7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate (and print errors) !
|
||||||
|
xmlSchemaSetValidErrors(schemValidator,
|
||||||
|
(xmlSchemaValidityErrorFunc) fprintf,
|
||||||
|
(xmlSchemaValidityWarningFunc) fprintf, stderr);
|
||||||
|
|
||||||
|
// Get the validation status
|
||||||
|
model->validated =
|
||||||
|
xmlSchemaValidateDoc(schemValidator, xmlDocument) == 0 ? true : false;
|
||||||
|
|
||||||
|
// Reset node
|
||||||
|
currentNode = xmlDocGetRootElement(xmlDocument);
|
||||||
|
|
||||||
|
// Parsing identity
|
||||||
|
currentNode = currentNode->xmlChildrenNode;
|
||||||
|
while (currentNode != NULL) {
|
||||||
|
for (int i = 0; i < identityParserTable.len; i++) {
|
||||||
|
if ((!xmlStrcmp(currentNode->name,
|
||||||
|
identityParserTable.table[i].tag))) {
|
||||||
|
identityParserTable.table[i].parse(xmlDocument,
|
||||||
|
&identityParserTable,
|
||||||
|
i,
|
||||||
|
currentNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentNode = currentNode->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlSchemaFreeValidCtxt(schemValidator);
|
||||||
|
xmlSchemaFree(schemPtr);
|
||||||
|
free(version);
|
||||||
|
xmlFreeDoc(xmlDocument);
|
||||||
|
free(schemPath);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------- //
|
||||||
|
// Parsing a model file //
|
||||||
|
// -------------------------------------------------------------------------- //
|
||||||
|
int ParseModelXML(Model_t *model)
|
||||||
|
{
|
||||||
|
xmlDocPtr xmlDocument;
|
||||||
|
xmlNodePtr currentNode;
|
||||||
|
|
||||||
|
ParserTableXML_t table[] =
|
||||||
|
{
|
||||||
// PARAMETERS
|
// PARAMETERS
|
||||||
{(const xmlChar *)"parameters", parseParentFieldPropsXML, model},
|
{(const xmlChar *)"parameters", parseParentFieldPropsXML, model},
|
||||||
// MODELIZATION
|
// MODELIZATION
|
||||||
|
@ -361,8 +510,6 @@ int ParseModelXML(Model_t *model)
|
||||||
};
|
};
|
||||||
|
|
||||||
printLog("Parsing model %s\n", model->name);
|
printLog("Parsing model %s\n", model->name);
|
||||||
xmlDocPtr xmlDocument;
|
|
||||||
xmlNodePtr currentNode;
|
|
||||||
|
|
||||||
xmlDocument = xmlParseFile(model->filename);
|
xmlDocument = xmlParseFile(model->filename);
|
||||||
|
|
||||||
|
@ -405,7 +552,5 @@ int ParseModelXML(Model_t *model)
|
||||||
|
|
||||||
xmlFreeDoc(xmlDocument);
|
xmlFreeDoc(xmlDocument);
|
||||||
|
|
||||||
// validate when we're finished
|
|
||||||
model->validated = true;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue