// GenericDataset.h #ifndef dset__GenericDataset_H #define dset__GenericDataset_H // David Adams // October 2004 // // Generic dataset description. Provides means for writing to and reading // from XML. // // The XML description includes the full type name. If this type is // registered, then its creator is used create the dataset from XML. // Otherwise the creator defined here is used. // // The location and content are stored in one of four states: // ABSENT - does not exist, e.g. no location for virtual dataset // EXPLICIT - held directly in the XML description // COMPOSITE - obtained by merging values from constituent datasets // IMPLICIT - evaluated in subclass, e.g. by reading data files or // extra data // // Subclasses are expected to define and register a "promoter", a // function that converts a generic dataset object into one of the // full type. Typically this is done by providing a ctor which takes // a generic dataset as an argument and then registering the promote // template defined at the end of this header. // // The dataset may or may not be an event dataset. This state and the // means to obtain the event list from the content are specified by // the event list flag: // EVNONE - this is not an event dataset // EVFIRST - event list is taken from the first content block // The clone operator here will attempt to promote its result and so // typical subclasses will not need to reimplement this method. // // Constituent datasets are extracted from the default dataset // repository on demand, i.e. in the call to constituents(). If // absent, they are registered there when appended here. // // The constituent datasets are not managed here. The user should take care // that their lifetime exceeds that of this dataset. // // XML representation (for this and typical subclasses): // // GenericDataset // fulltype = MyDataset // id = 123-456 // parent = 123-455 // owner = someone // create_time = 12345657890 // cstorage = explicit // lstorage = absent // is_event = true // Content // ... // Location // ... // InterfaceLocation // Location // ... // DatasetIdList // ... // ExtraData // // The extra data is optional. It is appended to the XML description if the // method extra_xml() returns nonzero. // // If the interface location is absent, then the location will be used // as the interface location. // #include #include #include "dataset_base/Content.h" #include "dataset_base/Location.h" #include "dataset_base/Dataset.h" namespace dset { class DatasetRepository; class GenericDataset : public Dataset { public: // typedefs // Name. typedef std::string Name; // Ordered list of names. typedef std::set NameList; // Pointer to a function which promotes a generic dataset into // a superclass. typedef const GenericDataset* (*Promoter) (const GenericDataset&); public: // enums // Storage state. enum StorageState { UNDEFINED, ABSENT, EXPLICIT, COMPOSITE, IMPLICIT }; // Event state. enum EventState { EVUNDEF, EVNONE, EVFIRST }; private: // data // Type. std::string m_fulltype; // Validity. int m_error; // Flag indicating dataset locked. bool m_locked; // ID. DatasetId m_id; // Parent ID. DatasetId m_pid; // Parent. mutable const Dataset* m_parent; // Owner. std::string m_owner; // Create time. Time m_create_time; // Content and location states. StorageState m_con_storage; StorageState m_loc_storage; // Event state. EventState m_evstate; // Content. mutable Content m_con; // Location. mutable Location m_loc; mutable Location m_iloc; // Constituent ID's. DatasetIdList m_dids; // Constituents. mutable DatasetList m_dsts; // Extra XML. const XmlElement* m_pxxml; bool m_manage_xxml; public: // static methods // Return the XML name. static const char* xml_name() { return "GenericDataset"; } // DTD. static const Text& dtd(); // Create from xml. // Caller is responsible for managing the new dataset. // Returns 0 if creation fails. static const GenericDataset* create(const XmlElement& ele, DatasetRepository* prep); // Register a promoter. // Superclasses should define and register such a function. // Return 0 for success. static int register_promoter(Name name, Promoter pfun); // Promote a generic dataset to its full type using the coresponding // promoter. // Caller is responsible for managing the returned dataset. // Returns 0 for failure (e.g. no promoter for the given name). static const GenericDataset* promote(const GenericDataset& dst); // Return if a promoter name is registered. static bool has_promoter(Name name); // Return the names for which promoters have been registered. static const NameList& promoters(); private: // Hidden functions. // Assignment. GenericDataset& operator=(const GenericDataset& rhs); protected: // const protected methods // Return the content storage state. StorageState content_storage_state() const { return m_con_storage; } // Return the location storage state. StorageState location_storage_state() const { return m_loc_storage; } // Create extra XML. // Subclasses which wish to record extra XML data should implement // this method and return a nonzero value. // The default implementation here returns null. // Returned object is owned by the caller. virtual const XmlElement* create_extra_xml() const; // Return the extra XML. // Returned object is *not* owned by the caller. const XmlElement* extra_xml() const; protected: // non-const protected methods // These setter are used by subclasses during construction. // None of these have any effect after the dataset is invalidated // or locked. // All return // 0 for success // 1 if the dataset is invalid // 2 if the dataset is locked // Set full type. int set_fulltype(std:: string fulltype); // Set invalid. // Error is set to 999. int set_invalid(); // Set error. // Argument should be nonzero and dataset should be valid. // Errpor is set and dataset becomes invalid. int set_error(int err); // Set the content storage state to undefined. // ANY --> UNDEFINED. int unset_content(); // Set the content storage state to absent. // UNDEFINED -> ABSENT. // Content is left empty. int set_content_absent(); // Set the content storage state to implicit. // UNDEFINED -> IMPLICIT. // Content is left empty. int set_content_implicit(); // Set the content storage state to composite. // UNDEFINED -> COMPOSITE. // Content is left empty. int set_content_composite(); // Set the content. // UNDEFINED -> EXPLICIT. int set_content(const Content& con); // Update the content. // EXPLICIT -> EXPLICIT. int reset_content(const Content& con); // Merge into the content. // EXPLICIT -> EXPLICIT. int merge_content(const Content& con); // Set the location implicit. // Location state goes from UNDEFINED -> IMPLICIT. int set_location_implicit(); // Set the location composite. // Location state goes from UNDEFINED -> COMPOSITE. int set_location_composite(); // Set the location. // Location state goes from UNDEFINED -> EXPLICIT. // The second argument is the interface location, if defined. int set_location(const Location& loc, const Location* piloc =0); // Set virtual (no location). // Location state goes from UNDEFINED -> ABSENT. int set_virtual(); // Return mutable reference to the location. Location& mutable_location() const { return m_loc; } // Return mutable reference to the interface location. Location& mutable_interface_location() const { return m_iloc; } // Set event content to none. // EVUNDEF -> EVNONE. int set_evstate_none(); // Set event content to use the first content block. // EVUNDEF -> EVFIRST. int set_evstate_first(); // Provide access to modify the list of constituent ID's. // Null pointer returned if dataset is invalid or locked. int set_constituent_ids(const DatasetIdList& dids); // Append a constituent dataset ID. int append_constituent_id(DatasetId did, bool allow_dup =false); // Append a constituent dataset. // The dataset is registered in the default DB if not // already present. int append_constituent(const Dataset& dst, bool allow_dup =false); public: // Constructors, destructor and clone. // Default constructor. // State is valid and unlocked with content and location undefined. GenericDataset(); // Constructor for an invalid dataset. // Locked if argument is true. GenericDataset(bool lock); // Constructor for a virtual dataset with no constituents. // con = content of the dataset // fulltype = full type (default is GenericDataset) // id = ID (generated automatically if invalid or missing) GenericDataset(const Content& con, std::string fulltype =xml_name(), DatasetId id = DatasetId()); // Constructor for a nonvirtual dataset with no constituents. // con = content of the dataset // fulltype = full type (default is GenericDataset) // id = ID (generated automatically if invalid or missing) GenericDataset(const Content& con, const Location& loc, std::string fulltype =xml_name(), DatasetId id = DatasetId()); // Constructor for a nonvirtual dataset with no constituents. // and interface location different from location. // con = content of the dataset // fulltype = full type (default is GenericDataset) // id = ID (generated automatically if invalid or missing) GenericDataset(const Content& con, const Location& loc, const Location& iloc, std::string fulltype =xml_name(), DatasetId id = DatasetId()); // Constructor from XML. GenericDataset(const XmlElement& ele); // Copy constructor. GenericDataset(const GenericDataset& rhs); // Destructor. ~GenericDataset(); public: // inherited const interface // Return the full type. std::string fulltype() const; // Validity. bool is_valid() const; // Error status. int error() const; // Emptiness. bool is_empty() const; // Return the ID. DatasetId id() const; // Return the parent ID. DatasetId parent_id() const; // Return the parent. const Dataset* parent() const; // Return the owner. std::string owner() const; // Return the create time. Time create_time() const; // Return the lock status. bool is_locked() const; // Content. const Content& content() const; // Is virtual. bool is_virtual() const; // Location. const Location& location() const; // Interface location. const Location& interface_location() const; // Return if this is an event dataset. bool is_event_dataset() const; // Return the event count. EventIdList::size_type event_count() const; // Return the list of event_ids. const EventIdList& event_ids() const; // Return the constituent dataset ID's. // Default is empty. const DatasetIdList& constituent_ids() const; // Return the constituent datasets. // If absent, these are constructed from the constituent ID // list and the default dataset repository. // The list will have null entries for ID's that cannot be // retrieved. const DatasetList& constituents() const; // Clone. // This attempts to promote the new dataset and thus should suffice // for most subclasses. GenericDataset* clone(std::string dir ="") const; // Release. // If subdatasets are created, then each of them is released. // If there are no sub-datasets, then the logical files in the // location are released. int release() const; // Return XML representation. const XmlElement* xml() const; // Return the memory allocated to this object. // Sizes for ID lists (sets) are likely underestimated. size_t memsize() const; public: // inherited non-const interface // Lock. // ID must be valid. // Content and location must be defined. // If not, dataset becomes invalid. int lock(); // Set the dataset ID. // The dataset must be unlocked and the current ID must be local. // Returns the ID if successful. // Otherwise returns an invalid ID. int set_id(const DatasetId& id); // Set the ID using unique ID generator. int set_id(); // Set the parent ID using the provided value. // Fails if a valid ID is already assigned. // Inherited method set_parent(...) can be used instead. int set_parent_id(const DatasetId& did); // Set the parent dataset and ID. // This dataset must be unlocked. // The parent must be locked. int set_parent(const Dataset& dst); // Merge another dataset. // This implementation fails. int merge(const Dataset& dst, std::string dir =""); // Select content. // Dataset must be valid and unlocked. // Returns 0 for success. // This implementation fails because it does not hold the // mapping of content to location or constituents. int select(const Content& con); // Select events. int select_events(const EventIdList& eids); }; // Template for promoters. template const GenericDataset* promote(const GenericDataset& gen) { return new T(gen); } } // end namespace dset #endif