/*
 * cccc_db.h
 * 
 * defines the database used by CCCC to generate a report
 */
#ifndef CCCC_DB_H
#define CCCC_DB_H

#include <iostream.h>
#include <iomanip.h>

#include "cccc_stg.h"
#include "cccc_met.h"
#include "cccc_tbl.h"

#include "cccc_utl.h"

// these are generic classes, used to implement the relational model
// for the application
class CCCC_Field;
class CCCC_Record;

// these are the types of the entities in this application's relational 
// model
class CCCC_Project;
class CCCC_Module;
class CCCC_Member;
class CCCC_UseRelationship;
class CCCC_Extent;


// The entities held within the database need to be able to return a variety 
// of kinds of name including a simple name (typically one word), a fully 
// qualified local name (i.e as used within a class), and a fully 
// qualified global name.
// They also need to be able to supply a key for searching, which must be 
// unique within the table, and a ranking string, which need not be unique
// and may contain artificial elements to enforce appropriate ordering.
// subclasses may also have particular other names, which should be defined
// using negative indexes
enum NameLevel { nlRANK, nlSEARCH, nlSIMPLE, nlLOCAL, nlGLOBAL };
class CCCC_Record 
{
  friend class CCCC_Html_Stream;
protected:
  CCCC_Table<CCCC_Extent,10> extent_table;
  CCCC_Field flags;
  virtual void merge_flags(CCCC_Field& new_flags);
public:
  virtual char* name(int level) const;
  virtual char* ranking_string() const;
  virtual char* key() const;

  virtual void add_extent(istream&);
  virtual void sort() { extent_table.sort(); }
  virtual void generate_report(ostream &os);
  virtual int get_count(const char *count_tag);
  friend int rank_by_string(const void *p1, const void *p2);
};


class CCCC_Project : public CCCC_Record 
{
  CCCC_String project_name;

public:
  CCCC_Table<CCCC_Module,10000> module_table;
  CCCC_Table<CCCC_Member,10000> member_table;
  CCCC_Table<CCCC_UseRelationship,10000> userel_table;
  CCCC_Table<CCCC_Extent,10000> rejected_extent_table;

  CCCC_Project(const CCCC_String& name="");
  char* name(int level) const { return project_name; }
  void add_module(istream& module_data_line);
  void add_member(istream& member_data_line);    
  void add_userel(istream& use_data_line);
  void add_rejected_extent(istream& rejected_data_line);

  void sort();
  void assign_anonymous_members();
  int get_count(const char *count_tag);
  void generate_report(ostream&);
};

enum ModuleNameLevel 
{ nlMODULE_TYPE=-1, nlMODULE_NAME=-2, nlMODULE_TYPE_AND_NAME=-3 };

enum RelationshipMaskElements 
{ 
  rmeCLIENT=0x01, rmeSUPPLIER=0x02, 
  rmeHIDDEN=0x10, rmeVISIBLE=0x20, rmeHIDDEN_OR_VISIBLE=0x30,
  rmeABSTRACT=0x40, rmeCONCRETE=0x80, rmeABSTRACT_OR_CONCRETE=0xC0
};

class CCCC_Module : public CCCC_Record 
{
  friend class CCCC_Project;
  CCCC_Field module_name, module_type;
public:
  CCCC_Table<CCCC_Member,1000> member_table;
  char* name(int name_level) const; 
    
  CCCC_Module(istream& module_data_line);

  void generate_report(ostream&);
  int get_count(const char *count_tag);
  int get_relationships(CCCC_Project *prj, int mask,
			CCCC_UseRelationship**& rel_array);
  int is_trivial();
};

enum MemberNameLevel { nlMEMBER_NAME=-1, nlMEMBER_TYPE=-2, nlMEMBER_PARAMS=-3 };

class CCCC_Member : public CCCC_Record 
{
  friend class CCCC_Project;
  friend class CCCC_Module;
  CCCC_Field member_type, member_name, param_list;
  CCCC_Module *parent;
public:
  char *name( int index ) const;
  CCCC_Member(istream& member_data_line, CCCC_Module* parent_ptr=NULL);
  void generate_report(ostream&); 
  int get_count(const char *count_tag);
};

enum ExtentNameLevel { nlFILENAME=-1, nlLINENUMBER=-2, nlDESCRIPTION=-3};
class CCCC_Extent : public CCCC_Record 
{
  friend class CCCC_Record;
  friend class CCCC_Project;
  
  CCCC_Field filename;
  CCCC_Field linenumber;
  CCCC_Field description;
  CCCC_Field flags;
  CCCC_Field count_buffer;
  UseType ut;
  Visibility v;
public:
  CCCC_Extent();
  CCCC_Extent(istream& is);

  char *name( int index ) const;
  void generate_report(ostream &os);
  Visibility get_visibility() const { return v; }
  int get_count(const char *count_tag);
  UseType get_usetype() const { return ut; }
  const CCCC_String& get_description() const { return description; }
};

enum UserelNameLevel { nlSUPPLIER=-1, nlCLIENT=-2, nlMEMBER=-3 };
class CCCC_UseRelationship : public CCCC_Record 
{
  CCCC_Field supplier, client, member;
  UseType ut;
  AugmentedBool visible, concrete;
public:
  char *name( int index ) const;
  CCCC_UseRelationship(istream& is);
  void add_extent(istream&);
  int get_count(const char *count_tag);
  UseType get_usetype() const { return ut; }
  AugmentedBool is_visible () const { return visible; }
  AugmentedBool is_concrete () const { return concrete; }
  void generate_report(ostream& os);
  CCCC_Module* supplier_module_ptr(CCCC_Project *prj);
  CCCC_Module* client_module_ptr(CCCC_Project *prj);
};


#endif // CCCC_DB_H






