/************************************************************
   Copyright (C) 1993 by The Trustees of Columbia University in the City 
   of New York

   OBJECT-ORIENTED Protein Data Bank Project
   Biochemistry and Molecular Biophysics, Computer Science depts.
 **************************************************************

   File: iterator.h
   Responsable: Weider Chang, Ph.D

 **************************************************************/

#ifndef _H_ITERATOR
#define _H_ITERATOR

#include "structure.h"


/*********************************************************************
				Iterators

FUNCTION

Iterators are designed for application programmer who wants to inspect
diferent objects' elements at different abstraction levels.

It contains 1 pointer to an element, whose abstraction level is
depicted by the name of Iterator itself - in this case, user can inspect a
protein, chain, secondary structure, subentity by looking at atom, subentity,
chain, or secondary structure levels,..

USAGE


Use AtomIter, ResidueIter, EntityIter, and SecondaryIter to denote the level
of abstraction you want to inspect.

Use const & SubEntity, & Entity, & SecondaryStruc, and & Compound as arguments
to indicate the object you want to inspect.

Example:

// To browse all the atoms of a protein, we can:
for ( AtomIter it(p1); it; ++it) {
	// Atom Iter it(p1)  	declare iterator it to look at all atoms in p1
	// ++it			advance to next element
	// it			null after reach the end of protein
	// it()			const & Atom

	cout << it().d_name;

}


***********************************************************************/

class EntityIter {
	Entity * entity_p;
public:
	EntityIter();
	EntityIter( const Compound& protein );
	EntityIter( const Entity&);
	~EntityIter();
	operator const void * () const;
	const Entity& operator() () const ;
	void operator++();
	void operator--();
};

class SecondaryStrucIter {
	SecondaryStruc * d_secondary_p;
public:
	SecondaryStrucIter();
	SecondaryStrucIter( const Compound& protein );
	~SecondaryStrucIter();
	operator const void * () const;
	const SecondaryStruc& operator() ()const ;
	void operator++();
	void operator--();
};

class SubEntityIter {
	EntityIter d_cit;
	SubEntity * subentity_p;  // moving subentity
	SubEntity * subentity1_p; // starting redisue    secondary structures
	SubEntity * subentity2_p;	// ending subentity: for secondary structures
	int d_f_stop;		// to indicate stop at secondary structure end
	int d_b_stop;		// to indicate stop at secondary structure beg
public:
	SubEntityIter();
	SubEntityIter( const Compound& protein );
	SubEntityIter( const Entity& chain );
	SubEntityIter( const SecondaryStruc& secondarystruc );
	SubEntityIter( const SubEntity&);    /* weider */
	~SubEntityIter();
	operator const void * () const;
//	const 
        SubEntity& operator() ()const ;
	void operator++();
	void operator--();
};

class AltAtomIter {
  Atom * main_chain_atom_p;
  Atom * atom_p;
  int nth_alt;
 public:
  AltAtomIter();
  AltAtomIter( const Atom& atom );
  operator const void * () const;
  Atom& operator() () const;
  void operator++();
  void operator--();
};


class AtomIter {
  Atom * d_atom_p;
  SubEntityIter d_rit;
  int iter_alt_atom;
  int nth_alt;
 public:
  AtomIter();
  AtomIter( const Compound& protein, int =0);
  AtomIter( const Entity& chain, int =0 );
  AtomIter( const SecondaryStruc& secondarystruc, int =0);
  AtomIter( const SubEntity& subentity, int =0 );
  ~AtomIter();
  operator const void * () const;
  const Atom& operator() ()const;
  void operator++();
  void operator--();
};


/****************************************************************************

				Filters

FUNCTIONS

Filters are designed for application programmer who wants to inspect
diferent objects' elements at different abstraction levels. And only those
element(s) that fit into the criteria as depicted in 2nd argument.

It contains 1 pointer to an element, whose abstraction level is
depicted by the name of Filters itself - in this case, user can inspect a
protein, chain, secondary structure, subentity by looking at atom, subentity,
chain, or secondary structure levels,..

USAGE


Use AtomFilter, SubEntityFilter, EntityFilter, and SecondaryFilter to denote the
level of abstraction you want to inspect.

Use const & SubEntity, & Entity, & SecondaryStruc, and & Compound as 1 st arguments
to indicate the object you want to inspect.

Use char * or int as 2nd arguments to indicate the criteria, such as name or no.

Example:

// To browse all the subentitys of a protein that has name of "SYS", we can:
for ( SubEntityFilter it(p1); it; ++it) {
	// SubEntityFilter it(p1, "SYS") 	declare filter it to look at subentitys
	//				in protein p1 that has name of "SYS"
	// ++it				advance to next "SYS" element
	// it				null when no "SYS" left
	// it()				const & SubEntity

	cout << it().d_name;

}

****************************************************************************/



class EntityFilt {
	EntityIter d_cit;
	Entity * entity_p;
	int d_pos;
	char* d_id;

public:
	EntityFilt();
//	EntityFilt( const Compound& protein, int position );
	EntityFilt( const Compound& protein, char* id);
	~EntityFilt();
	operator const void * () const;
	Entity& operator() ();
	void operator++();
};


class SecondaryStrucFilt {
	SecondaryStruc * d_secondary_p;
public:
	SecondaryStrucFilt();
//	SecondaryStrucFilt( const Compound& protein, int position );
//	SecondaryStrucFilt( const Compound& protein, char* id );
	~SecondaryStrucFilt();
	operator const void * () const;
	const SecondaryStruc& operator() ()const ;
	void operator++();
};

class SubEntityFilt {
	SubEntityIter d_rit;
	SubEntity * subentity_p;
	int d_seq_no;
	char* d_name;

public:
	SubEntityFilt();
	SubEntityFilt( const Entity& e, int position);
	SubEntityFilt( const Entity& e, char* name);
//	SubEntityFilt( const Entity& e, char*, int);
//	SubEntityFilt( const SecondaryStruc& secondarystruc, int position);
//	SubEntityFilt( const SecondaryStruc& secondarystruc, char* name);
	~SubEntityFilt();
	operator const void * () const;
	SubEntity& operator() () ;
	void operator++();
};

class AtomFilt {
  
  Atom * d_atom_p;
  AtomIter d_ait;
  int d_no;
  char *d_name;
 public:
  AtomFilt();
  AtomFilt( const Compound& protein, int no);
  AtomFilt( const Compound& protein, char* name);
  AtomFilt( const Entity& chain, int no);
  AtomFilt( const Entity& chain, char* name);
  
//	AtomFilt( const SecondaryStruc& secondarystruc, int no);
//	AtomFilt( const SecondaryStruc& secondarystruc, char* name);

//	AtomFilt( const SubEntity& subentity, int position);
//	AtomFilt( const SubEntity& subentity, char* name);

  ~AtomFilt();
  operator const void * () const;
  Atom& operator() ();
  void operator++();
  
};

#endif















