DMBCore is a small library aimed to utilize VL for building and using external data models in end applications. It relies on such VL extentions and features as JSONConverter and Prototyping.
The main data model stored in the root of a JSON file can be considered as a database as it has an organized collection of structured data including not only the output data model used in an application directly, but also an underlying part including the internal data structure that is used for storing the application’s data in convenient, reusable, and extensible way.
With DMBCore there is no need to manually convert vl::Object to JSON including JSONConverter to your project and writing your own TypeResolver. All these steps are encapsulated inside one library which also provides some additional features as initial database structure.
The database program interface is represented by class dmb::Model (called Model as it is an internal data model of the database). It includes and maintains the following data structures:
(see example “Empty database”)
The main intention of the implementation is to separate the resulting data model used by an end app from internal structures that are used as a building bricks for the data model construction.
DMBCore also allows the end app to use internal types (from the “types” field) to modify and extend the existent data model.
The end application uses a data model which is created specifically for it. That model is stored in the “content” field of the database.
The “types” section comprises of composite types (that is containing several properties in self) represented by vl::Object. These types are used in the “content” field that in turn comprises fields of any types. It may be a Basic type, List or Object. If it is a composite type from “types” section then it is a vl::Object with “proto” field set to type’s id (see the example below “Type used in Content").
Private types are composites too, but they can’t be used in the content. The only purpose to use private types is to construct some type in “types” section.
VL Prototyping feature is utilized for:
Prototyping is used to let an end application use types from the “types” section. Every type is used as a prototype for any instance of it in the “content” field. A designer of a data model creates types and may instantiate any of them into the content, and the end application may use instances directly from the content or instantiate it’s own during the runtime, put them into the content, store and then load for the future reuse. Thus DMBCore provides the full stack of operations with data:
(see the example “In-content types”)
The ideology of DMBCore as of any DBMS implies separation between a database creation and utilization. Designing a model for an application is nothing but creating a “content” field of a database.
Creating a database in terms of DMBCore implies:
There is a user-friendly application with GUI based on Qt called DataModelBuilder that is aimed to fully cover the creation process of a database.
As an alternative you can create a database without DataModelBuilder using any text editor writing and modifying JSON content of the database.
Utilization of a database means:
The following examples show how the data is stored in JSON format using DMBCore.
dmb::Model in initial state is convertable to the following JSON:
{
"content": {},
"types": {},
"private": {}
}
Every section is a vl::Object converted to JSON object.
The composite type “Skill” is referenced as a prototype in object “rootSkill” located in the content
{
"content": {
"rootSkill": {
"proto": "Skill",
"name": "Root skill"
}
},
"types": {
"Skill": {
"name": "Skill"
}
},
"private": {}
}
Here you can see how the prototyping VL feature can be used to set any object as a prototype of another. It means that you can create your own types during the runtime of the application and store them in the content for reusing.
{
"content": {
"rootSkill": {
"proto": "Skill",
"children": [
{
"proto": "content.skillLibrary.[0]",
"x": 6.0,
"y": 2.0,
"children": []
},
{
"proto": "content.skillLibrary.[2]",
"x": 1.0,
"y": 5.0,
"children": []
}
]
},
"skillLibrary": [
{
"proto": "Skill",
"description": "The Programming skill",
"name": "Programming",
"iconPath": "resources/programming.jpg"
},
{
"proto": "Skill",
"description": "The Development skill",
"name": "Development",
"iconPath": "resources/development.png"
},
{
"proto": "Skill",
"description": "",
"name": "C++",
"iconPath": "resources/c++.png"
}
]
},
"types": {
"Skill": {
"name": "Skill",
"frameImgPath": "resources/border.png",
"description": "",
"iconPath": "",
"children": []
}
},
"private": {}
}
Here we can see several fields in the content with different types:
{
"fruitTree": {
"typeid": "bush",
"leafColor": "Gold",
"isTree": true,
"y": 0.0,
"leafPerBranch": 6.0,
"branches": [
{
"leafCount": 9.0,
"fruit": {},
"branches": [
{
"leafCount": 3.0,
"fruit": {
"isFruit": true,
"color": "Yellow",
"radius": 0.30000001192092896,
"branchCount": 1.0
},
"branches": []
}
]
}
],
"x": 0.0
},
"fieldSize": 4.0,
"animalsAround": [
{
"typeid": "animal",
"type": "bear",
"isMammal": true
},
{
"typeid": "animal",
"type": "bird"
},
{}
]
}
DMBCore uses JSON as a format for storing and loading the data. VL extension JSONConverter covers this need.
dmb::Model model;
// Here are fields of the database allowed through the hight-level interfaces Registry and Content
auto& registry = model.GetRegistry();
auto& privateScope = model.GetPrivateScope();
auto& content = model.GetContent();
// … continuing the previous example …
auto& animal = registry.CreateType("animal");
// reference vl::Object& of a newly created type anmial
// is returned
// … continuing the previous example …
auto& tree = content.Add("fruitTree", model.GetType("bush"));
tree.Set("leafColor", "Gold");
content.Add("fieldSize", vl::NumberVar(4));
auto& animals = content.Add("animalsAround", vl::List()).AsList();
// … continuing the previous example …
animal.Set("type", "");
vl::Object bear;
bear.SetPrototype(animal);
bear.Set("type", "bear");
bear.Set("isMammal", true);
vl::Object bird;
bird.SetPrototype(animal);
bird.Set("type", "bird");
animals.Add(bear);
animals.Add(bird);
animals.Add(vl::Object());
// … continuing the previous example …
model.Store("output.json", { true });
The second argument is a structure named vl::CnvParams
struct CnvParams
{
bool pretty = false;
bool useProtoRefs = true;
bool storeTypeId = true;
};
And we have passed the first argument pretty as true to generate a visually structured JSON.
std::string fName = "model.json";
dmb::Model model;
if (model.Load(fName))
std::cout << "Model loaded from '" << fName << "'\n";
else
{
std::cout << "Error while loading a model from '" << fName << "'\n";
return;
}
QVL is a Qt plugin used to serve Qt data models (including ListModel and QObject) using VL and DMBCore as its data layer for Qt models. It also uses database control interface functions of DMBCore like Store and Load.