// -*- c++ -*-
// Generated by gtkmmproc -- DO NOT MODIFY!
#ifndef _LIBGDAMM_METASTORE_H
#define _LIBGDAMM_METASTORE_H


#include <glibmm.h>

// -*- C++ -*- //

/* metastore.h
 *
 * Copyright 2006 libgdamm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or(at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <libgdamm/connection.h>
#include <libgdamm/metastruct.h>


#ifndef DOXYGEN_SHOULD_SKIP_THIS
typedef struct _GdaMetaStore GdaMetaStore;
typedef struct _GdaMetaStoreClass GdaMetaStoreClass;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gnome
{

namespace Gda
{ class MetaStore_Class; } // namespace Gda

} // namespace Gnome
namespace Gnome
{

namespace Gda
{

class MetaStoreError : public Glib::Error
{
public:
  enum Code
  {
    META_STORE_INCORRECT_SCHEMA_ERROR,
    META_STORE_UNSUPPORTED_PROVIDER_ERROR,
    META_STORE_INTERNAL_ERROR,
    META_STORE_META_CONTEXT_ERROR,
    META_STORE_MODIFY_CONTENTS_ERROR,
    META_STORE_EXTRACT_SQL_ERROR,
    META_STORE_ATTRIBUTE_NOT_FOUND_ERROR,
    META_STORE_ATTRIBUTE_ERROR,
    META_STORE_SCHEMA_OBJECT_NOT_FOUND_ERROR,
    META_STORE_SCHEMA_OBJECT_CONFLICT_ERROR,
    META_STORE_SCHEMA_OBJECT_DESCR_ERROR,
    META_STORE_TRANSACTION_ALREADY_STARTED_ERROR
  };

  MetaStoreError(Code error_code, const Glib::ustring& error_message);
  explicit MetaStoreError(GError* gobject);
  Code code() const;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
private:

#ifdef GLIBMM_EXCEPTIONS_ENABLED
  static void throw_func(GError* gobject);
#else
  //When not using exceptions, we just pass the Exception object around without throwing it:
  static std::auto_ptr<Glib::Error> throw_func(GError* gobject);
#endif //GLIBMM_EXCEPTIONS_ENABLED

  friend void wrap_init(); // uses throw_func()
#endif
};

} // namespace Gda

} // namespace Gnome

#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gnome::Gda::MetaStoreError::Code> : public Glib::Value_Enum<Gnome::Gda::MetaStoreError::Code>
{
public:
  static GType value_type() G_GNUC_CONST;
};

} // namespace Glib
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gnome
{

namespace Gda
{


/** Dictionary object.
 *
 * Previous versions of Libgda relied on an XML based file to store dictionary 
 * information, such as the database's schema (tables, views, etc) and various 
 * other information. The problems were that it was difficult for an application
 * to integrate its own data into the dictionary and that there were some 
 * performances problems as the XML file needed to be parsed (and converted into 
 * its own in-memory structure) before any data could be read out of it.
 *
 * The new dictionary now relies on a database structure to store its data 
 * (see the database schema section for a detailled description). The actual 
 * database can be a single file (using an SQLite database), an entirely in 
 * memory database (also using an SQLite database), or a more conventional backend 
 * such as a PostgreSQL database for a shared dictionary on a server. 
 *
 * @ingroup Connection
 */

class MetaStore : public Glib::Object
{
  typedef GdaMetaContext MetaContext;
  
  
#ifndef DOXYGEN_SHOULD_SKIP_THIS

public:
  typedef MetaStore CppObjectType;
  typedef MetaStore_Class CppClassType;
  typedef GdaMetaStore BaseObjectType;
  typedef GdaMetaStoreClass BaseClassType;

private:  friend class MetaStore_Class;
  static CppClassType metastore_class_;

private:
  // noncopyable
  MetaStore(const MetaStore&);
  MetaStore& operator=(const MetaStore&);

protected:
  explicit MetaStore(const Glib::ConstructParams& construct_params);
  explicit MetaStore(GdaMetaStore* castitem);

#endif /* DOXYGEN_SHOULD_SKIP_THIS */

public:
  virtual ~MetaStore();

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  static GType get_type()      G_GNUC_CONST;


  static GType get_base_type() G_GNUC_CONST;
#endif

  ///Provides access to the underlying C GObject.
  GdaMetaStore*       gobj()       { return reinterpret_cast<GdaMetaStore*>(gobject_); }

  ///Provides access to the underlying C GObject.
  const GdaMetaStore* gobj() const { return reinterpret_cast<GdaMetaStore*>(gobject_); }

  ///Provides access to the underlying C instance. The caller is responsible for unrefing it. Use when directly setting fields in structs.
  GdaMetaStore* gobj_copy();

private:

protected:
  explicit MetaStore(const Glib::ustring& cnc_string);
  // TODO: cannot be overloaded, no filename property  
  //_WRAP_CTOR(MetaStore(const std::string& filename), gda_meta_store_new_with_file)

public:
  
  static Glib::RefPtr<MetaStore> create(const Glib::ustring& cnc_string);

  
  /** Get @a store's internal schema's version
   * 
   * Retunrs: the version (1 at the moment)
   */
  int get_version() const;
  
  /** Extracts some data stored in @a store using a custom SELECT query.
   * @param select_sql A SELECT statement.
   * @param Varargs A list of (variable name (gchar *), GValue *value) terminated with <tt>0</tt>, representing values for all the
   * variables mentionned in @a select_sql. If there is no variable then this part can be omitted.
   * @return A new Gda::DataModel, or <tt>0</tt> if an error occurred.
   */

#ifdef GLIBMM_EXCEPTIONS_ENABLED
  Glib::RefPtr<DataModel> extract(const Glib::ustring& sql);
#else
  Glib::RefPtr<DataModel> extract(const Glib::ustring& sql, std::auto_ptr<Glib::Error>& err);
#endif  
  
  /** Propagates an update to @a store, the update's contents is represented by @a new_data, this function is
   * primarily reserved to database providers.
   * 
   * For example tell @a store to update its list of tables, @a new_data should contain the same columns as the "_tables"
   * table of @a store, and contain one row per table in the store; there should not be any more argument after the @a error
   * argument.
   * 
   * Now, to update only one table, the @a new_data data model should have one row for the table to update (or no row
   * at all if the table does not exist anymore), and have values for the promary key of the "_tables" table of
   *  @a store, namely "table_catalog", "table_schema" and "table_name".
   * @param table_name The name of the table to modify within @a store.
   * @param new_data A Gda::DataModel containing the new data to set in @a table_name, or <tt>0</tt> (treated as a data model
   * with no row at all).
   * @param condition SQL expression (which may contain variables) defining the rows which are being obsoleted by @a new_data, or <tt>0</tt>.
   * @param Varargs A list of (variable name (gchar *), GValue *value) terminated with <tt>0</tt>, representing values for all the
   * variables mentionned in @a condition.
   * @return <tt>true</tt> if no error occurred.
   */

#ifdef GLIBMM_EXCEPTIONS_ENABLED
  bool modify(const Glib::ustring& sql, const Glib::RefPtr<DataModel>& data_model, const Glib::ustring& condition);
#else
  bool modify(const Glib::ustring& sql, const Glib::RefPtr<DataModel>& data_model, const Glib::ustring& condition, std::auto_ptr<Glib::Error>& err);
#endif
   
  
  /** Propagates an update to @a store, the update's contents is represented by @a new_data, this function is
   * primarily reserved to database providers.
   * @param context A Gda::MetaContext context describing what to modify in @a store.
   * @param new_data A Gda::DataModel containing the new data to set in @a table_name, or <tt>0</tt> (treated as a data model
   * with no row at all).
   * @return <tt>true</tt> if no error occurred.
   */
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  bool modify_with_context (MetaContext* context, const Glib::RefPtr<DataModel>& new_data);
#else
  bool modify_with_context(MetaContext* context, const Glib::RefPtr<DataModel>& new_data, std::auto_ptr<Glib::Error>& error);
#endif //GLIBMM_EXCEPTIONS_ENABLED


  /** Creates a new Gda::DataModelArray data model which can be used, after being correctly filled,
   * with the gda_meta_store_modify*() methods.*
   * 
   * To be used by provider's implementation
   * @param table_name The name of a table present in @a store.
   * @return A new Gda::DataModel.
   */
  Glib::RefPtr<DataModel> create_modify_data_model(const Glib::ustring& table_name);
  
  /** Creates a new Gda::MetaStruct object representing @a store's interal database structure.
   * @return A new Gda::MetaStruct object, or <tt>0</tt> if an error occurred.
   */
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  Glib::RefPtr<MetaStruct> schema_get_structure();
#else
  Glib::RefPtr<MetaStruct> schema_get_structure(std::auto_ptr<Glib::Error>& error);
#endif //GLIBMM_EXCEPTIONS_ENABLED

  
  /** Get an ordered list of the tables @a store knows about. The tables are ordered in a way that tables dependencies
   * are respected: if table B has a foreign key on table A, then table A will be listed before table B in the returned
   * list.
   * @return A new list of tables names (as gchar*), the list must be freed when no longer needed, 
   * but the strings present in the list must not be modified.
   */
  Glib::SListHandle<Glib::ustring> schema_get_all_tables();
  
  /** Get an ordered list of the tables @a store knows about on which the @a table_name table depends (recursively). 
   * The tables are ordered in a way that tables dependencies
   * are respected: if table B has a foreign key on table A, then table A will be listed before table B in the returned
   * list.
   * @param table_name The name of the table for which all the dependencies must be listed.
   * @return A new list of tables names (as gchar*), the list must be freed when no longer needed, 
   * but the strings present in the list must not be modified.
   */
  Glib::SListHandle<Glib::ustring> schema_get_depend_tables(const Glib::ustring& table_name);  

  
  /** The Gda::MetaStore object maintains a list of (name,value) attributes (attributes names starting with a '_'
   * character are for internal use only and cannot be altered). This method and the set_attribute_value()
   * method allows the user to add, set or remove attributes specific to their usage.
   * 
   * This method allows to get the value of a attribute stored in @a store. The returned attribute value is 
   * placed at @a att_value, the caller is responsible to free that string. 
   * 
   * If there is no attribute named @a att_name then @a att_value is set to <tt>0</tt>
   * and @a error will contain the GDA_META_STORE_ATTRIBUTE_NOT_FOUND_ERROR error code, and <tt>false</tt> is returned.
   * @param att_name Name of the attribute to get.
   * @param att_value The place to store the attribute value.
   * @return <tt>true</tt> if no error occurred.
   */

#ifdef GLIBMM_EXCEPTIONS_ENABLED
   bool get_attribute_value(const Glib::ustring& att_name, Glib::ustring& att_value);
#else
   bool get_attribute_value(const Glib::ustring& att_name, Glib::ustring& att_value, std::auto_ptr<Glib::Error>);
#endif

  
  /** Set the value of the attribute named @a att_name to @a att_value; see get_attribute_value() for
   * more information.
   * @param att_name Name of the attribute to set.
   * @param att_value Value of the attribute to set, or <tt>0</tt> to unset the attribute.
   * @return <tt>true</tt> if no error occurred.
   */
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  bool set_attribute_value(const Glib::ustring& att_name, const Glib::ustring& att_value);
#else
  bool set_attribute_value(const Glib::ustring& att_name, const Glib::ustring& att_value, std::auto_ptr<Glib::Error>& error);
#endif //GLIBMM_EXCEPTIONS_ENABLED

  
  /** The internal database used by @a store can be 'augmented' with some user-defined database objects
   * (such as tables or views). This method allows one to add a new database object.
   * 
   * If the internal database already contains the object, then:
   * &lt;itemizedlist&gt;
   * &lt;listitem&gt;if the object is equal to the provided description then <tt>true</tt> is returned&lt;/listitem&gt;
   * &lt;listitem&gt;if the object exists but differs from the provided description, then <tt>false</tt> is returned,
   * with the GDA_META_STORE_SCHEMA_OBJECT_CONFLICT_ERROR error code&lt;/listitem&gt;
   * &lt;/itemizedlist&gt;
   * 
   * The @a xml_description defines the table of view's definition, for example:
   * &lt;![CDATA[&lt;table name="mytable"&gt;
   *     &lt;column name="id" pkey="<tt>true</tt>"/&gt;
   *     &lt;column name="value"/&gt;
   * &lt;/table&gt;]]&gt;
   * 
   * The partial DTD for this XML description of the object to add is the following (the top node must be
   * a &lt;table&gt; or a &lt;view&gt;):
   * &lt;![CDATA[&lt;!ELEMENT table (column*,check*,fkey*,unique*)&gt;
   * &lt;!ATTLIST table
   *           name NMTOKEN R::EQUIRED&gt;
   * 
   * &lt;!ELEMENT column EMPTY&gt;
   * &lt;!ATTLIST column
   *           name NMTOKEN R::EQUIRED
   *           type CDATA I::MPLIED
   *           pkey (<tt>true</tt>|<tt>false</tt>) I::MPLIED
   *           autoinc (<tt>true</tt>|<tt>false</tt>) I::MPLIED
   *           nullok (<tt>true</tt>|<tt>false</tt>) I::MPLIED&gt;
   * 
   * &lt;!ELEMENT check (P::CDATA)&gt;
   * 
   * &lt;!ELEMENT fkey (part+)&gt;
   * &lt;!ATTLIST fkey
   *           ref_table NMTOKEN R::EQUIRED&gt;
   * 
   * &lt;!ELEMENT part EMPTY&gt;
   * &lt;!ATTLIST part
   *           column NMTOKEN I::MPLIED
   *           ref_column NMTOKEN I::MPLIED&gt;
   * 
   * &lt;!ELEMENT unique (column*)&gt;
   * 
   * &lt;!ELEMENT view (definition)&gt;
   * &lt;!ATTLIST view
   *           name NMTOKEN R::EQUIRED
   *           descr CDATA I::MPLIED&gt;
   * 
   * &lt;!ELEMENT definition (P::CDATA)&gt;]]&gt;
   * @param xml_description An XML description of the table or view to add to @a store.
   * @return <tt>true</tt> if the new object has sucessfully been added.
   */
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  bool schema_add_custom_object(const Glib::ustring& xml_description);
#else
  bool schema_add_custom_object(const Glib::ustring& xml_description, std::auto_ptr<Glib::Error>& error);
#endif //GLIBMM_EXCEPTIONS_ENABLED

  
  /** Removes the custom database object named @a obj_name.
   * @param obj_name Name of the custom object to remove.
   * @return <tt>true</tt> if the custom object has sucessfully been removed.
   */
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  bool schema_remove_custom_object(const Glib::ustring& obj_name);
#else
  bool schema_remove_custom_object(const Glib::ustring& obj_name, std::auto_ptr<Glib::Error>& error);
#endif //GLIBMM_EXCEPTIONS_ENABLED


  /** Get a pointer to the Gda::Connection object internally used by @a store to store
   * its contents.
   * 
   * The returned connection can be used to access some other data than the one managed by @a store
   * itself. The returned object is not owned by the caller (if you need to keep it, then use Glib::object_ref()).
   * Do not close the connection.
   * @return A Gda::Connection, or <tt>0</tt>.
   */
  Glib::RefPtr<Connection> get_internal_connection();
  
  /** Get a pointer to the Gda::Connection object internally used by @a store to store
   * its contents.
   * 
   * The returned connection can be used to access some other data than the one managed by @a store
   * itself. The returned object is not owned by the caller (if you need to keep it, then use Glib::object_ref()).
   * Do not close the connection.
   * @return A Gda::Connection, or <tt>0</tt>.
   */
  Glib::RefPtr<const Connection> get_internal_connection() const;

  // The rest of the properties is Write / Construct Only
  #ifdef GLIBMM_PROPERTIES_ENABLED
/** Connection object internally used.
   *
   * You rarely need to use properties because there are get_ and set_ methods for almost all of them.
   * @return A PropertyProxy that allows you to get or set the property of the value, or receive notification when
   * the value of the property changes.
   */
  Glib::PropertyProxy_ReadOnly< Glib::RefPtr<Connection> > property_cnc() const;
#endif //#GLIBMM_PROPERTIES_ENABLED

  
  /**
   * @par Prototype:
   * <tt>void on_my_%meta_reset()</tt>
   */

  Glib::SignalProxy0< void > signal_meta_reset();

  // TODO: do we need this?
  // See http://bugzilla.gnome.org/show_bug.cgi?id=574736
  //#m4 __CONVERSION(`gpointer',`MetaContext*',`(MetaContext*)($3)')
  //_WRAP_SIGNAL(gpointer suggest_update(MetaContext*  suggest), "suggest-update", no_default_handler)
  // Listhandle...
  // _WRAP_SIGNAL(void meta_changed(Glib::SListHandle<>))


public:

public:
  //C++ methods used to invoke GTK+ virtual functions:
#ifdef GLIBMM_VFUNCS_ENABLED
#endif //GLIBMM_VFUNCS_ENABLED

protected:
  //GTK+ Virtual Functions (override these to change behaviour):
#ifdef GLIBMM_VFUNCS_ENABLED
#endif //GLIBMM_VFUNCS_ENABLED

  //Default Signal Handlers::
#ifdef GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED
  virtual void on_meta_reset();
#endif //GLIBMM_DEFAULT_SIGNAL_HANDLERS_ENABLED


};

} // namespace Gda
} // namespace Gnome


namespace Glib
{
  /** A Glib::wrap() method for this object.
   * 
   * @param object The C instance.
   * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
   * @result A C++ instance that wraps this C instance.
   *
   * @relates Gnome::Gda::MetaStore
   */
  Glib::RefPtr<Gnome::Gda::MetaStore> wrap(GdaMetaStore* object, bool take_copy = false);
}


#endif /* _LIBGDAMM_METASTORE_H */

