bool listAllSeries(const std::string& rootCategory, const std::string& outputFile) { bool result(false); using namespace fredcpp; // Initialize Api api; api.withLogger(external::SimpleLogger::getInstance()) .withExecutor(external::CurlHttpClient::getInstance()) .withParser(external::PugiXmlParser::getInstance()) ; external::SimpleLogger::getInstance().enableInfo(); FREDCPP_LOG_INFO(FREDCPP_FACILITY << " version " << FREDCPP_VERSION_STRING << " (" << FREDCPP_BRIEF << ")"); FREDCPP_LOG_INFO("Getting API key from environment variable " << ENV_API_KEY << " ..."); api.withKey(getKeyFromEnv(ENV_API_KEY)); // Build a list of available sub-categories under the root FREDCPP_LOG_INFO("Building list of available sub-categories of category " << rootCategory << " ..."); ChildrenByIdMap categoryTree; if ( 0 == buildCategoryTree(api, categoryTree, rootCategory)) { FREDCPP_LOG_FATAL("Unable to retrieve categories"); exit(EXIT_FAILURE); } FREDCPP_LOG_INFO("Available categories count:" << categoryTree.size()); FREDCPP_LOG_INFO("Creating output data file " << outputFile << " ..."); std::ofstream output(outputFile.c_str()); if (!output) { exitOnBadOutputFile(outputFile); } // Get series IdSet uniqueSeries; ApiResponse response; for (ChildrenByIdMap::iterator it = categoryTree.begin(); it != categoryTree.end(); ++it) { std::string categoryId(it->first); api.get(ApiRequestBuilder::CategorySeries(categoryId) , response) || exitOnApiError(response); if (!response.entities.size()) { FREDCPP_LOG_INFO("category:" << categoryId << " contains no series"); } // Print series // NOTE: a given series can belong to multiple categories, // so keep track of unique series for (std::size_t n = 0; n < response.entities.size(); ++n) { std::string seriesId (response.entities[n].attribute("id")); if (uniqueSeries.find(seriesId) != uniqueSeries.end()) { continue; } uniqueSeries.insert(seriesId); output << response.entities[n].attribute("id") << "|" << response.entities[n].attribute("frequency_short") << "|" << response.entities[n].attribute("title") << "|" << response.entities[n].attribute("observation_start") << "|" << response.entities[n].attribute("observation_end") << "|" << std::endl; } } // Report stats FREDCPP_LOG_INFO("root-category:" << rootCategory << " sub-categories-count:" << categoryTree.size() - 1 << " series-count:" << uniqueSeries.size()); output.close(); FREDCPP_LOG_INFO("Successfully created file " << outputFile); result = true; return (result); }
std::size_t buildCategoryTree(fredcpp::Api& api, ChildrenByIdMap& tree, const std::string& rootCategory) { std::size_t categoryCount; using namespace fredcpp; tree.clear(); // Request children categories for sub-categories starting from rootCategory std::string parentId(rootCategory); // Add top-level categories categoryCount = addCategoryToTree(api, tree, parentId); if (categoryCount == 0) { return (categoryCount); } std::list<IdSet> parentLevels; IdSet parents; IdSet children = tree[parentId]; if (children.size()) { parentLevels.push_back(children); } else { return (categoryCount); } while (parentLevels.size()) { parents = parentLevels.front(); for (IdSet::iterator itNextParent = parents.begin(); itNextParent != parents.end(); ++itNextParent) { for (IdSet::iterator itChild = children.begin(); itChild != children.end(); ++itChild) { std::string childId(*itChild); //FREDCPP_LOG_INFO("category:" << childId << " parent:" << parentId); categoryCount += addCategoryToTree(api, tree, childId); } parentId = *itNextParent; children = tree[parentId]; if (children.size()) { parentLevels.push_back(children); } } parentLevels.pop_front(); } return (categoryCount); }