// Location.cxx #include "dataset_base/Location.h" #include #include "dataset_util/Text.h" #include "dataset_util/XmlElement.h" #include "dataset_util/DtdRegistry.h" using std::string; using std::ostream; using std::cerr; using std::endl; using dset::Location; typedef Location::UrlList UrlList; //********************************************************************** // Local definitions. //********************************************************************** namespace { // Maximum # files to print. unsigned int MAX_PRINT_LFILE = 20; // Url DTD. const Text& urldtd() { static Text txt; if ( txt.size() == 0 ) { txt.append(""); txt.append(""); } return txt; } // Register the DTD. const DtdRegistry::Status stat_Location_dtd = DtdRegistry::register_dtd("dataset"); // Register the Url DTD. const DtdRegistry::Status stat_Url_dtd = DtdRegistry::instance("dataset").add_type("Url", urldtd()); } //********************************************************************** // Static member functions. //********************************************************************** // DTD. const Text& Location::dtd() { static Text txt; if ( txt.size() == 0 ) { //txt.append(""); txt.append(""); } return txt; } //********************************************************************** // Member functions. //********************************************************************** // Empty or invalid constructor. Location::Location(int error) : m_error(error) { } //********************************************************************** // XML constructor. Location::Location(const XmlElement& ele) : m_error(0) { if ( ele.name() != xml_name() ) return; for ( XmlElement::ElementList::const_iterator iele=ele.children().begin(); iele!=ele.children().end(); ++iele ) { const XmlElement& child = **iele; if ( child.name() == "LogicalFile" ) { cerr << "Location::ctor: Found obselete reference to LogicalFile" << endl; cerr << ele << endl; assert(false); // LogicalFile lfile(child); // if ( ! lfile.is_valid() ) { // m_error = 1; // break; // } // logical_files().push_back(lfile); } else if ( child.name() == "Url" ) { string surl = child.attribute("url"); Url url(surl); if ( ! url.is_valid() ) { m_error = 2; break; } files().push_back(url); } else { m_error = 3; break; } } } //********************************************************************** // Validity. bool Location::is_valid() const { return m_error == 0; } //********************************************************************** // Error status. int Location::error() const { return m_error; } //********************************************************************** // Is empty. bool Location::is_empty() const { return is_valid() && files().size() == 0; } //********************************************************************** // Return the const list of files. const UrlList& Location::files() const { return m_files; } //********************************************************************** // Return the mutable list of files. UrlList& Location::files() { return m_files; } //********************************************************************** // Memory size. size_t Location::memsize() const { size_t mem = 0; mem += sizeof(m_error); for ( UrlList::const_iterator ifil=m_files.begin(); ifil!=m_files.end(); ++ifil ) { mem += ifil->size(); } return mem; } //********************************************************************** // Write to XML. const XmlElement* Location::xml() const { if ( ! is_valid() ) return 0; XmlElement* pele = new XmlElement(xml_name()); for ( UrlList::const_iterator ifil=files().begin(); ifil!=files().end(); ++ifil ) { Url url = *ifil; string surl = url.to_string(); if ( surl.size() ) { XmlElement* pxurl = new XmlElement("Url"); pxurl->add_attribute("url", surl); pele->add_child(pxurl); } else { cerr << "Location:xml: Unable to extract XML" << endl; } } return pele; } //********************************************************************** // Output stream. ostream& Location:: ostr(ostream& lhs, string indent, string label) const { lhs << indent << label << " "; if ( ! is_valid() ) { lhs << "is invalid; error " << error(); return lhs; } if ( is_empty() ) { lhs << "is empty"; return lhs; } Location::UrlList::size_type nlfile = files().size(); lhs << "has " << nlfile << " file"; string indent2 = indent + " "; if ( nlfile != 1 ) lhs << "s"; if ( nlfile > 0 ) lhs << ":"; Location::UrlList::size_type count = 0; for ( Location::UrlList::const_iterator ifil=files().begin(); ifil!=files().end(); ++ifil ) { ++count; if ( nlfile > MAX_PRINT_LFILE && count>5 ) { ifil = files().end(); lhs << endl << indent2 << "..."; --ifil; } lhs << '\n'; Url url = *ifil; lhs << indent2 << url; } lhs.flush(); return lhs; } //********************************************************************** // Add another location to this. int Location::add(const Location& rhs) { if ( ! is_valid() ) return 1; if ( ! rhs.is_valid() ) return 2; if ( rhs.is_empty() ) { return 0; } const UrlList& files = rhs.files(); if ( is_empty() ) { m_files = files; return 0; } UrlList oldfiles = m_files; for ( UrlList::const_iterator ifil=files.begin(); ifil!=files.end(); ++ifil ) { Url url = *ifil; if ( ! url.is_valid() ) { m_files = oldfiles; return 1; } bool match = false; for ( UrlList::const_iterator jfil=m_files.begin(); jfil!=m_files.end(); ++jfil ) { if ( jfil->to_string() == url.to_string() ) { match = true; break; } } if ( ! match ) { m_files.push_back(url); } } return 0; } //********************************************************************** // Free functions. //********************************************************************** // Equality. bool dset::operator==(const Location& lhs, const Location& rhs) { const UrlList files = lhs.files(); const UrlList rfiles = rhs.files(); if ( files.size() != rfiles.size() ) return false; for ( UrlList::size_type ifil=0; ifil