void QrsMetamodelSaver::saveDiagram(qrRepo::RepoApi &repo, const Metamodel &metamodel
		, const QString &diagramName, const Id &metamodelId, Id &resultingId)
{
	const Id diagramId = metamodelDiagramType.sameTypeId();
	resultingId = diagramId;
	repo.addChild(metamodelId, diagramId);
	repo.setName(diagramId, diagramName);
	repo.setProperty(diagramId, "displayedName", metamodel.diagramFriendlyName(diagramName));
	if (const ElementType *node = metamodel.diagramNode(diagramName)) {
		repo.setProperty(diagramId, "nodeName", node->name());
	}

	QMap<const ElementType *, Id> elements;
	saveObjectsOnDiagram(repo, metamodel, diagramName, diagramId, elements);
	saveLinksInMetamodel(repo, metamodel, diagramName, diagramId, elements);
}
Id QrsMetamodelSaver::saveNode(qrRepo::RepoApi &repo, const NodeElementType &node, const Id &diagram)
{
	const Id nodeId = metamodelNodeType.sameTypeId();
	repo.addChild(diagram, nodeId);
	repo.setName(nodeId, node.name());
	repo.setProperty(nodeId, "displayedName", node.friendlyName());
	repo.setProperty(nodeId, "description", node.description());
	repo.setProperty(nodeId, "path", node.mouseGesture());
	repo.setProperty(nodeId, "abstract", node.isHidden());
	repo.setProperty(nodeId, "isResizeable", node.isResizable());
	repo.setProperty(nodeId, "createChildrenFromMenu", node.createChildrenFromMenu());

	saveSdfGraphics(repo, node, nodeId);
	saveContainerProperties(repo, node, nodeId);
	saveProperties(repo, node, nodeId);
	return nodeId;
}
Id QrsMetamodelSaver::saveEdge(qrRepo::RepoApi &repo, const EdgeElementType &edge, const Id &diagram)
{
	const Id edgeId = metamodelEdgeType.sameTypeId();
	repo.addChild(diagram, edgeId);
	repo.setName(edgeId, edge.name());
	repo.setProperty(edgeId, "displayedName", edge.friendlyName());
	repo.setProperty(edgeId, "description", edge.description());
	repo.setProperty(edgeId, "isDividable", edge.isDividable());
	repo.setProperty(edgeId, "lineType", penStyleToString(edge.penStyle()));
	repo.setProperty(edgeId, "shape", linkShapeToString(edge.shapeType()));

	const QList<LabelProperties> &labels = edge.labels();
	if (!labels.isEmpty()) {
		const LabelProperties &label = labels.first();
		repo.setProperty(edgeId, "labelText", label.isStatic() ? label.text() : label.binding());
		repo.setProperty(edgeId, "labelType", label.isStatic() ? "staticText" : "dynamicText");
		repo.setProperty(edgeId, "hardLabel", label.isHard());
	}

	saveAssociations(repo, edge, edgeId);
	saveProperties(repo, edge, edgeId);
	savePorts(repo, edge, edgeId, "from");
	savePorts(repo, edge, edgeId, "to");
	return edgeId;
}
void QrsMetamodelSaver::saveMetamodel(qrRepo::RepoApi &repo, const Metamodel &metamodel)
{
	const Id metamodelId = metamodelRootDiagramType.sameTypeId();
	repo.addChild(Id::rootId(), metamodelId);
	repo.setName(metamodelId, metamodel.id());
	repo.setProperty(metamodelId, "displayedName", metamodel.friendlyName());
	repo.setProperty(metamodelId, "version", metamodel.version());

	Id lastDiagramId;
	for (const QString &diagram : metamodel.diagrams()) {
		saveDiagram(repo, metamodel, diagram, metamodelId, lastDiagramId);
	}

	if (lastDiagramId.isNull()) {
		// Metamodel contained no diagrams, nowhere to save enums and ports, giving up.
		return;
	}

	for (const QString &enumName : metamodel.enumNames()) {
		saveEnum(repo, metamodel, enumName, lastDiagramId);
	}
}