Line data Source code
1 : /*! 2 : * \file esys/repo/manifest/xmlfileimpl_manifest.cpp 3 : * \brief 4 : * 5 : * \cond 6 : * __legal_b__ 7 : * 8 : * Copyright (c) 2020 Michel Gillet 9 : * Distributed under the MIT License. 10 : * (See accompanying file LICENSE.txt or 11 : * copy at https://opensource.org/licenses/MIT) 12 : * 13 : * __legal_e__ 14 : * \endcond 15 : * 16 : */ 17 : 18 : #include "esys/repo/esysrepo_prec.h" 19 : #include "esys/repo/manifest/xmlfileimpl.h" 20 : #include "esys/repo/manifest/xmlfile.h" 21 : 22 : #include <esysfile/xml/writer.h> 23 : #include <esysfile/xml/file.h> 24 : #include <esysfile/xml/attr.h> 25 : 26 : namespace esys::repo::manifest 27 : { 28 : 29 28 : XMLFileImpl::XMLFileImpl(XMLFile *self) 30 28 : : m_self(self) 31 : { 32 28 : } 33 : 34 56 : XMLFileImpl::~XMLFileImpl() = default; 35 : 36 25 : Result XMLFileImpl::read(const std::string &path) 37 : { 38 25 : esysfile::xml::File xml_file; 39 : 40 25 : xml_file.set_root_node_name("esysrepo_manifest"); 41 25 : int result = xml_file.read(path); 42 25 : if (result < 0) 43 : { 44 0 : self()->add_error(result, "XML parsing failed."); 45 0 : return ESYSREPO_RESULT(ResultCode::MANIFEST_ERROR_PARSING_FILE, path); 46 : } 47 : 48 50 : if (self()->get_data() == nullptr) self()->set_data(std::make_shared<Manifest>()); 49 : 50 25 : self()->get_data()->set_type(Type::ESYSREPO_MANIFEST); 51 : 52 50 : return read(xml_file.get_data()); 53 25 : } 54 : 55 25 : Result XMLFileImpl::read(std::shared_ptr<esysfile::xml::Data> data) 56 : { 57 25 : if (data->get_attrs().size() != 0) 58 : { 59 8 : Result result = read_root_attributes(data); 60 4 : if (result.error()) 61 : { 62 0 : self()->add_error(result.get_result_code_int(), "read_root_attributes failed."); 63 0 : return ESYSREPO_RESULT(result); 64 : } 65 4 : } 66 : else 67 42 : self()->get_data()->set_kind(manifest::Kind::ISOLATED); 68 : 69 25 : Result result; 70 : 71 102 : for (auto el : data->get_elements()) 72 : { 73 77 : if (el->get_name() == "location") 74 150 : result = read_location(el); 75 27 : else if ((el->get_name() == "default")) 76 75 : result = read_default(el); 77 2 : else if ((el->get_name() == "group")) 78 6 : result = read_group(el); 79 : else 80 0 : result = ESYSREPO_RESULT(ResultCode::MANIFEST_ELEMENT_UNKNOWN, el->get_name()); 81 77 : if (result.error()) 82 : { 83 0 : self()->add_error(result.get_result_code_int(), "Reading XML element failed : " + el->get_name()); 84 0 : return result; 85 : } 86 77 : } 87 25 : return ESYSREPO_RESULT(ResultCode::OK); 88 25 : } 89 : 90 4 : Result XMLFileImpl::read_root_attributes(std::shared_ptr<esysfile::xml::Element> root_el) 91 : { 92 8 : for (auto attr : root_el->get_attrs()) 93 : { 94 8 : Result result = read_root_attribute(attr); 95 4 : if (result.error()) return ESYSREPO_RESULT(result); 96 8 : } 97 4 : return ESYSREPO_RESULT(ResultCode::OK); 98 : } 99 : 100 4 : Result XMLFileImpl::read_root_attribute(std::shared_ptr<esysfile::xml::Attr> attr) 101 : { 102 4 : if (attr->get_name() != "kind") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR); 103 : 104 4 : manifest::Kind kind; 105 4 : Result result = convert(attr->get_value(), kind); 106 4 : if (result.error()) return ESYSREPO_RESULT(result, ResultCode::MANIFEST_KIND_UNKNOWN, attr->get_value()); 107 : 108 4 : self()->get_data()->set_kind(kind); 109 4 : return ESYSREPO_RESULT(ResultCode::OK); 110 4 : } 111 : 112 50 : Result XMLFileImpl::read_location(std::shared_ptr<esysfile::xml::Element> el) 113 : { 114 50 : if (el->get_name() != "location") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR); 115 : 116 50 : std::shared_ptr<Location> location = std::make_shared<Location>(); 117 : 118 50 : auto attr = el->get_attr("name"); 119 50 : if (attr != nullptr) 120 50 : location->set_name(attr->get_value()); 121 : else 122 0 : return ESYSREPO_RESULT(ResultCode::MANIFEST_LOCATION_WITHOUT_NAME); 123 : 124 100 : attr = el->get_attr("addr"); 125 50 : if (attr != nullptr) 126 50 : location->set_address(attr->get_value()); 127 : else 128 0 : return ESYSREPO_RESULT(ResultCode::MANIFEST_LOCATION_WITHOUT_ADDRESS); 129 : 130 100 : attr = el->get_attr("alt_addr"); 131 50 : if (attr != nullptr) location->set_alt_address(attr->get_value()); 132 : 133 50 : Result result; 134 : 135 329 : for (auto child_el : el->get_elements()) 136 : { 137 279 : if (child_el->get_name() == "repository") 138 1395 : result = read_repository(child_el, location); 139 : else 140 0 : result = ESYSREPO_RESULT(ResultCode::MANIFEST_ELEMENT_UNKNOWN, child_el->get_name()); 141 279 : if (result.error()) return result; 142 279 : } 143 : 144 150 : self()->get_data()->add_location(location); 145 50 : return ESYSREPO_RESULT(ResultCode::OK); 146 150 : } 147 : 148 279 : Result XMLFileImpl::read_repository(std::shared_ptr<esysfile::xml::Element> el, std::shared_ptr<Location> location) 149 : { 150 279 : if (el->get_name() != "repository") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR); 151 : 152 279 : auto repository = std::make_shared<Repository>(); 153 279 : repository->set_location(location.get()); 154 : 155 279 : auto attr = el->get_attr("name"); 156 279 : if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_REPOSITORY_WITHOUT_NAME); 157 279 : repository->set_name(attr->get_value()); 158 : 159 558 : attr = el->get_attr("path"); 160 279 : if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_REPOSITORY_WITHOUT_PATH); 161 279 : repository->set_path(attr->get_value()); 162 : 163 558 : attr = el->get_attr("revision"); 164 279 : if (attr != nullptr) repository->set_revision(attr->get_value()); 165 : 166 558 : location->add_repo(repository); 167 : 168 279 : return ESYSREPO_RESULT(ResultCode::OK); 169 558 : } 170 : 171 25 : Result XMLFileImpl::read_default(std::shared_ptr<esysfile::xml::Element> el) 172 : { 173 25 : if (el->get_name() != "default") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR); 174 : 175 75 : for (auto attr : el->get_attrs()) 176 : { 177 100 : Result result = read_default_attr(attr); 178 50 : if (result.error()) return result; 179 100 : } 180 25 : return ESYSREPO_RESULT(ResultCode::OK); 181 : } 182 : 183 50 : Result XMLFileImpl::read_default_attr(std::shared_ptr<esysfile::xml::Attr> attr) 184 : { 185 50 : if (attr->get_name() == "revision") 186 50 : self()->get_data()->set_default_revision(attr->get_value()); 187 25 : else if (attr->get_name() == "sync-j") 188 50 : self()->get_data()->set_default_job_count(atoi(attr->get_value().c_str())); 189 : else 190 0 : return ESYSREPO_RESULT(ResultCode::MANIFEST_ATTRIBUTE_UNKNOWN, attr->get_name()); 191 50 : return ESYSREPO_RESULT(ResultCode::OK); 192 : } 193 : 194 2 : Result XMLFileImpl::read_group(std::shared_ptr<esysfile::xml::Element> el) 195 : { 196 2 : auto attr = el->get_attr("name"); 197 2 : if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_GROUP_WITHOUT_NAME); 198 : 199 2 : std::shared_ptr<Group> group = std::make_shared<Group>(); 200 2 : group->set_name(attr->get_value()); 201 : 202 6 : for (auto child : el->get_elements()) 203 : { 204 16 : Result result = read_group_repo(child, group); 205 4 : if (result.error()) return ESYSREPO_RESULT(result); 206 8 : } 207 : 208 6 : self()->get_data()->get_groups().add_group(group); 209 : 210 2 : return ESYSREPO_RESULT(ResultCode::OK); 211 4 : } 212 : 213 4 : Result XMLFileImpl::read_group_repo(std::shared_ptr<esysfile::xml::Element> el, std::shared_ptr<Group> group) 214 : { 215 4 : if (el->get_name() != "repo") return ESYSREPO_RESULT(ResultCode::MANIFEST_GROUP_REPO_WITHOUT_NAME); 216 : 217 4 : auto attr = el->get_attr("path"); 218 4 : if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_GROUP_REPO_WITHOUT_PATH); 219 : 220 4 : auto repo = self()->get_data()->find_repo_by_path(attr->get_value()); 221 4 : if (repo == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_REPO_UNKNOWN, "path = " + attr->get_value()); 222 : 223 8 : group->add_repo(repo); 224 4 : return ESYSREPO_RESULT(ResultCode::OK); 225 8 : } 226 : 227 3 : Result XMLFileImpl::write_xml() 228 : { 229 6 : if (self()->get_data() == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_XML_DATA_NULLPTR); 230 : 231 3 : m_xml_data = std::make_shared<esysfile::xml::Data>(); 232 3 : m_xml_data->set_root_node_name("esysrepo_manifest"); 233 : 234 6 : if (self()->get_data()->get_kind() != manifest::Kind::ISOLATED) 235 : { 236 0 : std::string kind; 237 0 : Result result = convert(self()->get_data()->get_kind(), kind); 238 0 : if (result.error()) return ESYSREPO_RESULT(result); 239 0 : m_xml_data->add_attr("kind", kind); 240 0 : } 241 : 242 13 : for (auto location : self()->get_data()->get_locations()) 243 : { 244 28 : Result result = write(m_xml_data, location); 245 7 : if (result.error()) return ESYSREPO_RESULT(result); 246 14 : } 247 : 248 8 : for (auto group : self()->get_data()->get_groups().get_groups()) 249 : { 250 8 : Result result = write(m_xml_data, group); 251 2 : if (result.error()) return ESYSREPO_RESULT(result); 252 4 : } 253 3 : return ESYSREPO_RESULT(ResultCode::OK); 254 : } 255 : 256 1 : Result XMLFileImpl::write(const std::string &path) 257 : { 258 1 : Result result = write_xml(); 259 1 : if (result.error()) return ESYSREPO_RESULT(result); 260 : 261 1 : esysfile::xml::Writer writer; 262 : 263 1 : writer.set_indent(4); 264 2 : int result_int = writer.write(path, m_xml_data); 265 1 : if (result_int < 0) return ESYSREPO_RESULT(ResultCode::RAW_INT_ERROR, result_int); 266 1 : return ESYSREPO_RESULT(ResultCode::OK); 267 1 : } 268 : 269 2 : Result XMLFileImpl::write(std::ostream &os) 270 : { 271 2 : Result result = write_xml(); 272 2 : if (result.error()) return ESYSREPO_RESULT(result); 273 : 274 2 : esysfile::xml::Writer writer; 275 : 276 2 : writer.set_indent(4); 277 4 : int result_int = writer.write(os, m_xml_data); 278 2 : if (result_int < 0) return ESYSREPO_RESULT(ResultCode::RAW_INT_ERROR, result_int); 279 2 : return ESYSREPO_RESULT(ResultCode::OK); 280 2 : } 281 : 282 7 : Result XMLFileImpl::write(std::shared_ptr<esysfile::xml::Element> parent_el, std::shared_ptr<Location> location) 283 : { 284 7 : std::shared_ptr<esysfile::xml::Element> location_el = std::make_shared<esysfile::xml::Element>(); 285 : 286 7 : location_el->set_name("location"); 287 7 : location_el->add_attr("name", location->get_name()); 288 7 : location_el->add_attr("addr", location->get_address()); 289 : 290 77 : for (auto repo : location->get_repos()) 291 : { 292 280 : Result result = write(location_el, repo); 293 70 : if (result.error()) return ESYSREPO_RESULT(result); 294 140 : } 295 : 296 14 : parent_el->add_element(location_el); 297 7 : return ESYSREPO_RESULT(ResultCode::OK); 298 7 : } 299 : 300 70 : Result XMLFileImpl::write(std::shared_ptr<esysfile::xml::Element> parent_el, std::shared_ptr<Repository> repository) 301 : { 302 70 : std::shared_ptr<esysfile::xml::Element> repo_el = std::make_shared<esysfile::xml::Element>(); 303 : 304 70 : repo_el->set_name("repository"); 305 70 : repo_el->add_attr("path", repository->get_path()); 306 70 : repo_el->add_attr("name", repository->get_name()); 307 90 : if (!repository->get_revision().empty()) repo_el->add_attr("revision", repository->get_revision()); 308 : 309 140 : parent_el->add_element(repo_el); 310 70 : return ESYSREPO_RESULT(ResultCode::OK); 311 70 : } 312 : 313 2 : Result XMLFileImpl::write(std::shared_ptr<esysfile::xml::Element> parent_el, std::shared_ptr<Group> group) 314 : { 315 2 : std::shared_ptr<esysfile::xml::Element> grp_el = std::make_shared<esysfile::xml::Element>(); 316 : 317 2 : grp_el->set_name("group"); 318 2 : grp_el->add_attr("name", group->get_name()); 319 : 320 8 : for (auto repo : group->get_repos()) 321 : { 322 6 : std::shared_ptr<esysfile::xml::Element> repo_el = std::make_shared<esysfile::xml::Element>(); 323 : 324 6 : repo_el->set_name("repo"); 325 6 : repo_el->add_attr("path", repo->get_path()); 326 18 : grp_el->add_element(repo_el); 327 12 : } 328 : 329 4 : parent_el->add_element(grp_el); 330 2 : return ESYSREPO_RESULT(ResultCode::OK); 331 2 : } 332 : 333 194 : XMLFile *XMLFileImpl::self() 334 : { 335 194 : return m_self; 336 : } 337 : 338 0 : const XMLFile *XMLFileImpl::self() const 339 : { 340 0 : return m_self; 341 : } 342 : 343 : } // namespace esys::repo::manifest