31 if (!data.is_object())
35 if (data.contains(
"nodes") && data[
"nodes"].is_array())
39 if (data.contains(
"states") && data[
"states"].is_array())
51 return data.is_object() && data.contains(
"rootGraph");
62 std::cout <<
"[SubgraphMigrator] Blueprint is already in new format — skipping migration.\n";
68 std::cout <<
"[SubgraphMigrator] Blueprint does not require migration.\n";
72 std::cout <<
"[SubgraphMigrator] Migrating blueprint to flat-dictionary subgraph format...\n";
78 result[
"schema_version"] = 5;
80 std::cout <<
"[SubgraphMigrator] Migration complete.\n";
92 if (data.contains(
"nodes"))
94 if (data.contains(
"links"))
96 if (data.contains(
"rootNodeId"))
97 rootGraph[
"rootNodeId"] = data[
"rootNodeId"];
100 if (data.contains(
"states"))
102 if (data.contains(
"transitions"))
103 rootGraph[
"transitions"] = data[
"transitions"];
104 if (data.contains(
"initialState"))
105 rootGraph[
"initialState"] = data[
"initialState"];
110 newData[
"subgraphs"] = json::object();
120 const std::string&
uuid,
121 const std::string& blueprintType)
126 sg[
"blueprintType"] = blueprintType;
127 sg[
"inputPins"] = json::array();
128 sg[
"outputPins"] = json::array();
130 if (blueprintType ==
"HFSM")
132 sg[
"states"] = json::array();
133 sg[
"transitions"] = json::array();
134 sg[
"initialState"] =
"";
139 sg[
"nodes"] = json::array();
140 sg[
"links"] = json::array();
155 outError =
"Missing 'data' section.";
160 if (!data.contains(
"rootGraph") || !data.contains(
"subgraphs"))
162 outError =
"Blueprint is not in new subgraph format (missing rootGraph or subgraphs).";
169 outError =
"data.subgraphs must be a JSON object.";
180 outError =
"rootGraph references unknown subgraph UUID: " +
ref;
194 "' references unknown subgraph UUID: " +
ref;
203 std::vector<std::string>
visited;
204 std::vector<std::string>
inStack;
207 outError =
"Circular subgraph dependency detected starting from: " +
it.key();
221 std::vector<std::string>&
visited,
222 std::vector<std::string>&
inStack)
251 std::vector<std::string>
refs;
260 if (
node.is_object() &&
node.contains(
"subgraphUUID"))
262 const auto&
uuid =
node[
"subgraphUUID"];
264 refs.push_back(
uuid.get<std::string>());
272 for (
const auto& state :
graphObj[
"states"])
274 if (state.is_object() && state.contains(
"subgraphUUID"))
276 const auto&
uuid = state[
"subgraphUUID"];
278 refs.push_back(
uuid.get<std::string>());
ComponentTypeID GetComponentTypeID_Static()
Phase 8 — Migrates legacy blueprint data to the flat-dictionary subgraph format.
static bool HasCycle(const std::string &start, const nlohmann::json &subgraphs, std::vector< std::string > &visited, std::vector< std::string > &inStack)
void MigrateDataSection(nlohmann::json &blueprint) const
bool NeedsMigration(const nlohmann::json &blueprint) const
Returns true when the blueprint uses the legacy format (data.nodes exists at the top level of the dat...
static nlohmann::json MakeEmptySubgraph(const std::string &name, const std::string &uuid, const std::string &blueprintType)
Creates an empty subgraph definition JSON object.
bool IsNewFormat(const nlohmann::json &blueprint) const
Returns true when the blueprint is already in the Phase 8 format (data.rootGraph exists).
static bool ValidateSubgraphReferences(const nlohmann::json &blueprint, std::string &outError)
Validates that every subgraphUUID referenced by SubGraph nodes actually exists in data....
nlohmann::json Migrate(const nlohmann::json &blueprint) const
Migrates a legacy blueprint to the flat-dictionary format.
static std::vector< std::string > CollectSubgraphRefs(const nlohmann::json &graphObj)
< Provides AssetID and INVALID_ASSET_ID