attribute hydrator::read_attribute() { validate_current_element(dia_attribute); attribute attribute; attribute.name(read_xml_string_attribute(dia_name)); BOOST_LOG_SEV(lg, debug) << "Reading attribute: " << attribute.name(); const bool is_self_closing(reader_.is_empty()); if (!reader_.read()) { BOOST_LOG_SEV(lg, error) << unexpected_eod; BOOST_THROW_EXCEPTION(hydration_error(unexpected_eod)); } if (is_self_closing) return attribute; // no more content to read related to this attribute while (reader_.is_start_element()) { // are we inside an attribute? the attribute values below // should only appear if we are. const std::string name(reader_.name()); if (!is_attribute_value(name)) { BOOST_LOG_SEV(lg, error) << unsupported_value << name; BOOST_THROW_EXCEPTION(hydration_error(unsupported_value + name)); } if (name == dia_color) attribute.values().push_back(read_attribute_value<color>()); else if (name == dia_integer) attribute.values().push_back(read_attribute_value<integer>()); else if (name == dia_real) attribute.values().push_back(read_attribute_value<real>()); else if (name == dia_point) attribute.values().push_back(read_attribute_value<point>()); else if (name == dia_boolean) attribute.values().push_back(read_attribute_value<boolean>()); else if (name == dia_string) attribute.values().push_back(read_attribute_value<string>()); else if (name == dia_rectangle) attribute.values().push_back(read_attribute_value<rectangle>()); else if (name == dia_font) attribute.values().push_back(read_attribute_value<font>()); else if (name == dia_enum) attribute.values().push_back(read_attribute_value<enumeration>()); else if (name == dia_composite) attribute.values().push_back(read_attribute_value<composite>()); } // if we were not on a self-closing attribute tag, then we need to // consume the attribute end element. if (is_end_element(dia_attribute)) reader_.read(); return attribute; }
object hydrator::read_object() { validate_current_element(dia_object); object object; object.type(read_xml_string_attribute(dia_type)); object.version(read_xml_int_attribute(dia_version)); object.id(read_xml_string_attribute(dia_id)); BOOST_LOG_SEV(lg, debug) << "Reading object: '" << object.id() << "' of type: " << object.type(); if (!reader_.read()) { BOOST_LOG_SEV(lg, error) << unexpected_eod; BOOST_THROW_EXCEPTION(hydration_error(unexpected_eod)); } std::vector<attribute> attributes; do { if (is_start_element(dia_attribute)) attributes.push_back(read_attribute()); else if (is_start_element(dia_child_node)) object.child_node(read_child_node()); else if (is_start_element(dia_connections)) { object.connections(read_connections()); } else { BOOST_LOG_SEV(lg, warn) << "Skipping element: '" << reader_.name(); reader_.skip(); } } while (!is_end_element(dia_object)); reader_.read(); object.attributes(attributes); BOOST_LOG_SEV(lg, debug) << "Read object: " << object.id(); return object; }
void hydrator::next_element(std::string name) { if (!reader_.read()) { BOOST_LOG_SEV(lg, error) << unexpected_eod; BOOST_THROW_EXCEPTION(hydration_error(unexpected_eod)); } validate_current_element(name); }
void hydrator::validate_current_element(std::string name) const { if (reader_.name() != name || reader_.node_type() != utility::xml::node_types::element) { BOOST_LOG_SEV(lg, error) << unexpected_element << reader_.name(); BOOST_THROW_EXCEPTION( hydration_error(unexpected_element + reader_.name())); } }
void hydrator::validate_self_closing() const { const bool is_self_closing(reader_.is_empty()); if (!is_self_closing) { BOOST_LOG_SEV(lg, error) << expected_self_closing << reader_.name(); BOOST_THROW_EXCEPTION( hydration_error(expected_self_closing + reader_.name())); } }
composite hydrator::read_attribute_value() { composite result; result.type(read_xml_string_attribute(dia_type)); BOOST_LOG_SEV(lg, debug) << "Reading composite attribute value: " << result.type(); const bool is_self_closing(reader_.is_empty()); reader_.read(); if (is_self_closing) return result; typedef boost::shared_ptr<attribute> attribute_ptr; std::vector<attribute_ptr> attributes; typedef boost::shared_ptr<composite> composite_ptr; composite_ptr inner_composite; do { if (is_start_element(dia_composite)) { validate_self_closing(); if (inner_composite) { BOOST_LOG_SEV(lg, error) << expected_one_inner_composite; BOOST_THROW_EXCEPTION( hydration_error(expected_one_inner_composite)); } inner_composite = composite_ptr(new composite()); inner_composite->type(read_xml_string_attribute(dia_type)); result.inner_composite(inner_composite); reader_.skip(); } else if (is_start_element(dia_attribute)) { attribute_ptr ptr(new attribute(read_attribute())); attributes.push_back(ptr); } else { BOOST_LOG_SEV(lg, error) << unexpected_element; BOOST_THROW_EXCEPTION(hydration_error(unexpected_element)); } } while (!is_end_element(dia_composite)); result.value(attributes); reader_.skip(); // skip the composite end element return result; }
child_node hydrator::read_child_node() { validate_current_element(dia_child_node); child_node child_node; child_node.parent(read_xml_string_attribute(dia_parent)); validate_self_closing(); if (!reader_.read()) { BOOST_LOG_SEV(lg, error) << unexpected_eod; BOOST_THROW_EXCEPTION(hydration_error(unexpected_eod)); } return child_node; }
sample hydrator:: process_sample(const std::string& line, const unsigned int line_number) const { std::vector<std::string> tokens; boost::split(tokens, line, boost::is_space(), boost::token_compress_on); BOOST_LOG_SEV(lg, trace) << "Parsing line with tokens: " << tokens; if (tokens.size() < minimum_number_of_fields) { BOOST_LOG_SEV(lg, error) << missing_fields << ". Expected: " << minimum_number_of_fields << " Actual: " << tokens.size(); BOOST_THROW_EXCEPTION(hydration_error(missing_fields)); } unsigned int field_number(0); try { sample r; r.number(stoui(tokens[field_number])); const auto usi(stoi(tokens[++field_number])); r.unparsed_structure_identifier(usi); r.structure_identifier(to_structure_identifier_type(usi)); point p; p.x(stod(tokens[++field_number])); p.y(stod(tokens[++field_number])); p.z(stod(tokens[++field_number])); r.position(p); r.radius(stod(tokens[++field_number])); r.parent(stoi(tokens[++field_number])); r.line_number(line_number); return r; } catch (const std::invalid_argument& e) { BOOST_LOG_SEV(lg, error) << "Conversion error. Field " << field_number << ". Value: '" << tokens[field_number] << "'"; hydration_error he(invalid_field_value); he << error_in_field(field_number); throw he; } catch (const std::out_of_range& e) { BOOST_LOG_SEV(lg, error) << "Conversion error. Field " << field_number << ". Value: '" << tokens[field_number] << "'"; hydration_error he(invalid_field_value); he << error_in_field(field_number); throw he; } }
std::vector<connection> hydrator::read_connections() { validate_current_element(dia_connections); reader_.read(); std::vector<connection> r; do { if (!is_start_element(dia_connection)) { BOOST_LOG_SEV(lg, error) << unexpected_connection_type << reader_.name(); BOOST_THROW_EXCEPTION(hydration_error(unexpected_connection_type + reader_.name())); } r.push_back(read_connection()); } while (!is_end_element(dia_connections)); reader_.read(); BOOST_LOG_SEV(lg, debug) << "Object has " << r.size() << " connections"; return r; }
diagram_data hydrator::read_diagram_data() { next_element(dia_diagramdata); diagram_data diagram_data; BOOST_LOG_SEV(lg, debug) << "Reading diagram data."; if (!reader_.read()) { BOOST_LOG_SEV(lg, error) << unexpected_eod; BOOST_THROW_EXCEPTION(hydration_error(unexpected_eod)); } std::vector<attribute> attributes; do { attributes.push_back(read_attribute()); } while (!is_end_element(dia_diagramdata)); reader_.read(); diagram_data.attributes(attributes); BOOST_LOG_SEV(lg, debug) << "Read diagram data."; return diagram_data; }
model hydrator::hydrate(const boost::filesystem::path& p) const { const auto gs(p.generic_string()); BOOST_LOG_SEV(lg, debug) << "Parsing file: " << gs; boost::filesystem::ifstream s(p); if (s.fail()) { BOOST_LOG_SEV(lg, error) << failed_to_open_file << ": " << gs; BOOST_THROW_EXCEPTION(hydration_error(failed_to_open_file + gs)); } try { auto r(hydrate(s)); r.name(p.stem().generic_string()); BOOST_LOG_SEV(lg, debug) << "Parsed file successfully."; return r; } catch(boost::exception& e) { const auto s(p.generic_string()); BOOST_LOG_SEV(lg, error) << "Failed to parse file: " << s; e << error_in_file(s); throw; } }