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 printLog(FORMAT, ...) printf("\e[0m" LOGMSG " " FORMAT "\e[0m", \
|
||||
__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]))
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xmlschemas.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -66,4 +67,6 @@ int parseTextField(xmlDocPtr,
|
|||
|
||||
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;
|
||||
time_t t;
|
||||
int returnValue = 0;
|
||||
Parameters_t *parameters;
|
||||
|
||||
// Get parameters TODO from args
|
||||
parameters = (Parameters_t*) calloc(sizeof(Parameters_t), 1);
|
||||
Parameters_t parameters;
|
||||
|
||||
while ((options = getopt(argc, argv, ":C:M:U:")) != -1) {
|
||||
switch (options) {
|
||||
case 'C':
|
||||
printLog("Config : %s\n", optarg);
|
||||
parameters->configDir = (char*) malloc(strlen(optarg) + 1);
|
||||
strcpy(parameters->configDir, optarg);
|
||||
parameters.configDir = (char*) calloc(1, strlen(optarg) + 1);
|
||||
strcpy(parameters.configDir, optarg);
|
||||
break;
|
||||
case 'M':
|
||||
printLog("Models : %s\n", optarg);
|
||||
parameters->modelDir = (char*) malloc(strlen(optarg) + 1);
|
||||
strcpy(parameters->modelDir, optarg);
|
||||
parameters.modelDir = (char*) calloc(1, strlen(optarg) + 1);
|
||||
strcpy(parameters.modelDir, optarg);
|
||||
break;
|
||||
case 'U':
|
||||
printLog("User : %s\n", optarg);
|
||||
parameters->userDir = (char*) malloc(strlen(optarg) + 1);
|
||||
strcpy(parameters->userDir, optarg);
|
||||
parameters.userDir = (char*) calloc(1, strlen(optarg) + 1);
|
||||
strcpy(parameters.userDir, optarg);
|
||||
break;
|
||||
case ':':
|
||||
printLog("Option missing argument : %c\n", optopt);
|
||||
if (parameters->configDir)
|
||||
free(parameters->configDir);
|
||||
if (parameters.configDir)
|
||||
free(parameters.configDir);
|
||||
|
||||
if (parameters->modelDir)
|
||||
free(parameters->modelDir);
|
||||
if (parameters.modelDir)
|
||||
free(parameters.modelDir);
|
||||
|
||||
if (parameters->userDir)
|
||||
free(parameters->userDir);
|
||||
if (parameters.userDir)
|
||||
free(parameters.userDir);
|
||||
|
||||
free(parameters);
|
||||
return ENOSYS;
|
||||
break;
|
||||
case '?':
|
||||
printLog("Unknown option : %c\n", optopt);
|
||||
if (parameters->configDir)
|
||||
free(parameters->configDir);
|
||||
if (parameters.configDir)
|
||||
free(parameters.configDir);
|
||||
|
||||
if (parameters->modelDir)
|
||||
free(parameters->modelDir);
|
||||
if (parameters.modelDir)
|
||||
free(parameters.modelDir);
|
||||
|
||||
if (parameters->userDir)
|
||||
free(parameters->userDir);
|
||||
if (parameters.userDir)
|
||||
free(parameters.userDir);
|
||||
|
||||
free(parameters);
|
||||
return ENOSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parameters->configDir | !parameters->modelDir | !parameters->userDir) {
|
||||
if (!parameters.configDir | !parameters.modelDir | !parameters.userDir) {
|
||||
printLog("Missing arguments\n");
|
||||
|
||||
if (parameters->configDir)
|
||||
free(parameters->configDir);
|
||||
if (parameters.configDir)
|
||||
free(parameters.configDir);
|
||||
|
||||
if (parameters->modelDir)
|
||||
free(parameters->modelDir);
|
||||
if (parameters.modelDir)
|
||||
free(parameters.modelDir);
|
||||
|
||||
if (parameters->userDir)
|
||||
free(parameters->userDir);
|
||||
if (parameters.userDir)
|
||||
free(parameters.userDir);
|
||||
|
||||
free(parameters);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
|
@ -127,7 +121,7 @@ int main(int argc, char **argv)
|
|||
server = (Server_t*) calloc(1, sizeof(Server_t));
|
||||
|
||||
// Initializing model system
|
||||
ModelSystemInit(parameters);
|
||||
ModelSystemInit(¶meters);
|
||||
|
||||
// Launching server
|
||||
ServerInit(server);
|
||||
|
@ -141,11 +135,9 @@ int main(int argc, char **argv)
|
|||
free(server);
|
||||
server = NULL;
|
||||
|
||||
free(parameters->userDir);
|
||||
free(parameters->modelDir);
|
||||
free(parameters->configDir);
|
||||
free(parameters);
|
||||
parameters = NULL;
|
||||
free(parameters.userDir);
|
||||
free(parameters.modelDir);
|
||||
free(parameters.configDir);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
|
|
@ -272,13 +272,17 @@ void ModelSystemInit(Parameters_t *parameters)
|
|||
extensionPosition - modelDirEntry->d_name);
|
||||
|
||||
// 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);
|
||||
continue;
|
||||
};
|
||||
|
||||
// Check model is valid and/or parsed
|
||||
if (newModel->validated == false) {
|
||||
printLog("Deleting invalid model %s from known list\n",
|
||||
newModel->name);
|
||||
ModelDelete(newModel->id);
|
||||
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[] =
|
||||
{
|
||||
// IDENTITY
|
||||
{(const xmlChar *)"identity", parseParentFieldXML, model},
|
||||
{(const xmlChar *)"identity", parseParentFieldXML, NULL},
|
||||
{(const xmlChar *)"name", parseTextFieldXML, model->name},
|
||||
{(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 *)"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
|
||||
{(const xmlChar *)"parameters", parseParentFieldPropsXML, model},
|
||||
// MODELIZATION
|
||||
|
@ -361,8 +510,6 @@ int ParseModelXML(Model_t *model)
|
|||
};
|
||||
|
||||
printLog("Parsing model %s\n", model->name);
|
||||
xmlDocPtr xmlDocument;
|
||||
xmlNodePtr currentNode;
|
||||
|
||||
xmlDocument = xmlParseFile(model->filename);
|
||||
|
||||
|
@ -405,7 +552,5 @@ int ParseModelXML(Model_t *model)
|
|||
|
||||
xmlFreeDoc(xmlDocument);
|
||||
|
||||
// validate when we're finished
|
||||
model->validated = true;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue