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


#include <glibmm/ustring.h>
#include <sigc++/sigc++.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:

  static void throw_func(GError* gobject);

  friend void wrap_init(); // uses throw_func()

  #endif //DOXYGEN_SHOULD_SKIP_THIS
};

} // 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
{

/** @addtogroup libgdammEnums libgdamm Enums and Flags */

/**
 * @ingroup libgdammEnums
 * @par Bitwise operators:
 * <tt>%SqlIdentifierStyle operator|(SqlIdentifierStyle, SqlIdentifierStyle)</tt><br>
 * <tt>%SqlIdentifierStyle operator&(SqlIdentifierStyle, SqlIdentifierStyle)</tt><br>
 * <tt>%SqlIdentifierStyle operator^(SqlIdentifierStyle, SqlIdentifierStyle)</tt><br>
 * <tt>%SqlIdentifierStyle operator~(SqlIdentifierStyle)</tt><br>
 * <tt>%SqlIdentifierStyle& operator|=(SqlIdentifierStyle&, SqlIdentifierStyle)</tt><br>
 * <tt>%SqlIdentifierStyle& operator&=(SqlIdentifierStyle&, SqlIdentifierStyle)</tt><br>
 * <tt>%SqlIdentifierStyle& operator^=(SqlIdentifierStyle&, SqlIdentifierStyle)</tt><br>
 */
enum SqlIdentifierStyle
{
  SQL_IDENTIFIERS_LOWER_CASE = 1 << 0,
  SQL_IDENTIFIERS_UPPER_CASE = 1 << 1
};

/** @ingroup libgdammEnums */
inline SqlIdentifierStyle operator|(SqlIdentifierStyle lhs, SqlIdentifierStyle rhs)
  { return static_cast<SqlIdentifierStyle>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); }

/** @ingroup libgdammEnums */
inline SqlIdentifierStyle operator&(SqlIdentifierStyle lhs, SqlIdentifierStyle rhs)
  { return static_cast<SqlIdentifierStyle>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)); }

/** @ingroup libgdammEnums */
inline SqlIdentifierStyle operator^(SqlIdentifierStyle lhs, SqlIdentifierStyle rhs)
  { return static_cast<SqlIdentifierStyle>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs)); }

/** @ingroup libgdammEnums */
inline SqlIdentifierStyle operator~(SqlIdentifierStyle flags)
  { return static_cast<SqlIdentifierStyle>(~static_cast<unsigned>(flags)); }

/** @ingroup libgdammEnums */
inline SqlIdentifierStyle& operator|=(SqlIdentifierStyle& lhs, SqlIdentifierStyle rhs)
  { return (lhs = static_cast<SqlIdentifierStyle>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs))); }

/** @ingroup libgdammEnums */
inline SqlIdentifierStyle& operator&=(SqlIdentifierStyle& lhs, SqlIdentifierStyle rhs)
  { return (lhs = static_cast<SqlIdentifierStyle>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs))); }

/** @ingroup libgdammEnums */
inline SqlIdentifierStyle& operator^=(SqlIdentifierStyle& lhs, SqlIdentifierStyle rhs)
  { return (lhs = static_cast<SqlIdentifierStyle>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs))); }

} // namespace Gda

} // namespace Gnome


#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Glib
{

template <>
class Value<Gnome::Gda::SqlIdentifierStyle> : public Glib::Value_Flags<Gnome::Gda::SqlIdentifierStyle>
{
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
   * @return The version (incremented each time the schema changes, backward compatible).
   */
  int get_version() const;
  
  /** Extracts some data stored in @a store using a custom SELECT query. If the @a select_sql filter involves
   * SQL identifiers (such as table or column names), then the values should have been adapted using
   * sql_identifier_quote().
   * 
   * For more information about
   * SQL identifiers are represented in @a store, see the
   * meta data section about SQL identifiers.
   * @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 mentioned 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.
   */


  Glib::RefPtr<DataModel> extract(const Glib::ustring& sql);

  
  /** 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 primary 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 mentioned in @a condition.
   * @return <tt>true</tt> if no error occurred.
   */

  bool modify(const Glib::ustring& sql, const Glib::RefPtr<DataModel>& data_model, const Glib::ustring& condition);

  
  /** 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.
   */
  bool modify_with_context(MetaContext* context, const Glib::RefPtr<DataModel>& new_data);

  
  /** 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);
  
  /** Specifies how @a store must handle SQL identifiers it has to store. This method is mainly used by
   * database providers.
   * 
   * @newin{4,2}
   * @param style A style.
   */
  void set_identifiers_style(SqlIdentifierStyle style);
  
  /** Creates a new Gda::MetaStruct object representing @a store's internal database structure.
   * @return A new Gda::MetaStruct object, or <tt>0</tt> if an error occurred.
   */
  Glib::RefPtr<MetaStruct> schema_get_structure();
  
 
  /** 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.
   */
  std::vector<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.
   */
  std::vector<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 for 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.
   */

   bool get_attribute_value(const Glib::ustring& att_name, Glib::ustring& att_value);

  
  /** 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.
   */
  bool set_attribute_value(const Glib::ustring& att_name, const Glib::ustring& att_value);
  
  /** 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:
   * <itemizedlist>
   * <listitem>if the object is equal to the provided description then <tt>true</tt> is returned</listitem>
   * <listitem>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</listitem>
   * </itemizedlist>
   * 
   * The @a xml_description defines the table of view's definition, for example:
   * <![CDATA[<table name="mytable">
   *     <column name="id" pkey="<tt>true</tt>"/>
   *     <column name="value"/>
   * </table>]]>
   * 
   * The partial DTD for this XML description of the object to add is the following (the top node must be
   * a <table> or a <view>):
   * <![CDATA[<!ELEMENT table (column*,check*,fkey*,unique*)>
   * <!ATTLIST table
   *           name NMTOKEN R::EQUIRED>
   * 
   * <!ELEMENT column EMPTY>
   * <!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>
   * 
   * <!ELEMENT check (P::CDATA)>
   * 
   * <!ELEMENT fkey (part+)>
   * <!ATTLIST fkey
   *           ref_table NMTOKEN R::EQUIRED>
   * 
   * <!ELEMENT part EMPTY>
   * <!ATTLIST part
   *           column NMTOKEN I::MPLIED
   *           ref_column NMTOKEN I::MPLIED>
   * 
   * <!ELEMENT unique (column*)>
   * 
   * <!ELEMENT view (definition)>
   * <!ATTLIST view
   *           name NMTOKEN R::EQUIRED
   *           descr CDATA I::MPLIED>
   * 
   * <!ELEMENT definition (P::CDATA)>]]>
   * @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.
   */
  bool schema_add_custom_object(const Glib::ustring& xml_description);
  
  /** 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.
   */
  bool schema_remove_custom_object(const Glib::ustring& obj_name);

  
  /** 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 are 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 these?
  //_WRAP_SIGNAL(GError* suggest_update(MetaContext*  suggest), "suggest-update", no_default_handler)
  //_WRAP_SIGNAL(void meta_changed(std::vector<>))


public:

public:
  //C++ methods used to invoke GTK+ virtual functions:

protected:
  //GTK+ Virtual Functions (override these to change behaviour):

  //Default Signal Handlers::
  virtual void on_meta_reset();


};

} // 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 */

