/**********************************************************************
 *
 * collectserver.h -- 
 * Copyright (C) 1999  The New Zealand Digital Library Project
 *
 * A component of the Greenstone digital library software
 * from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id$
 *
 *********************************************************************/


#ifndef COLLECTSERVER_H
#define COLLECTSERVER_H

// Library header files
#include "gsdlconf.h"
#include "text_t.h"
#include "comtypes.h"
#include "filter.h"
#include "source.h"
#include "cfgread.h"
#include "cnfgable.h" 
#include "maptools.h"

#if defined(GSDL_USE_OBJECTSPACE)
#  include <ospace\std\iostream>
#elif defined(GSDL_USE_IOS_H)
#  include <iostream.h>
#else
#  include <iostream>
#endif

#if defined(GSDL_USE_OBJECTSPACE)
#  include <ospace\std\map>
#elif defined(GSDL_USE_STL_H)
#  include <map.h>
#else
#  include <map>
#endif


struct colservrconf {
  text_t gsdlhome;
  text_t collecthome;
  text_t dbhome;
  text_t collection;
  text_t collectdir;
};


class collectserver : public configurable {
protected:
  colservrconf configinfo;
  ColInfoResponse_t collectinfo;

  filtermapclass filters;
  sourcelistclass sources;

  // some stuff to remember while we are configuring
  stringmap indexmap;

public:
  collectserver ();
  virtual ~collectserver ();

  // add_filter makes another filter available to the collection server
  // the filter remains the property of the calling code and that
  // code should destroy the filter after the collection server has been
  // destroyed.
  void add_filter (filterclass *thefilter) {filters.addfilter(thefilter);}
  filtermapclass *get_filtermap_ptr () {return &filters;}

  // add_source makes another source available to the collection server
  // the source remains the property of the calling code and that
  // code should destroy the source after the collection server has been
  // destroyed.
  void add_source (sourceclass *thesource) {sources.addsource(thesource);}
  sourcelistclass *get_sourcelist_ptr () {return &sources;}

  // configure should be called for each line in the
  // configuration files to configure the collection server and everything
  // it contains. The configuration should take place just before initialisation.
  virtual void configure (const text_t &key, const text_tarray &cfgline);
  void configure (const text_t &key, const text_t &value);
  const colservrconf &get_configinfo () {return configinfo;}
  text_t get_collection_name () {return configinfo.collection;}
  bool is_collection_group () {return collectinfo.isCollectGroup;}


  // ping indicates whether the collection has appropriate data structures
  // to be active or not
  void ping(bool &wasSuccess, comerror_t &err, ostream &logout);

  // init should be called after the collection name has been set and
  // all initialisation is done. init returns true if the initialisation
  // was successful, if false is returned then no other functions
  // should be called (without producing meaningless output).
  virtual bool init (ostream &logout);

  void get_collectinfo (ColInfoResponse_t &reponse,
			comerror_t &err, ostream &logout);

  virtual void get_filterinfo (InfoFiltersResponse_t &response,
			       comerror_t &err, ostream &logout);

  virtual void get_filteroptions (const InfoFilterOptionsRequest_t &request,
				  InfoFilterOptionsResponse_t &response, 
				  comerror_t &err, ostream &logout);

  virtual void filter (FilterRequest_t &request,
		       FilterResponse_t &response,
		       comerror_t &err, ostream &logout);


  virtual void get_document (const DocumentRequest_t &request,
			     DocumentResponse_t &response,
			     comerror_t &err, ostream &logout);

  virtual void is_searchable (bool &issearchable, comerror_t &err,
			      ostream &logout);

};


// The collectserverptr function does not 'own' the collectserver. The
// collectserver should be deleted by the code which created it.
class collectserverptr {
public:
  collectserver *c;

  collectserverptr () {c=NULL;}
  ~collectserverptr () {}
};

bool operator==(const collectserverptr &x, const collectserverptr &y);
bool operator<(const collectserverptr &x, const collectserverptr &y);

typedef map<text_t, collectserverptr, lttext_t> collectserverptrmap;

// contains a list of collectservers indexed by their name
class collectservermapclass {
protected:
  collectserverptrmap collectserverptrs;

public:
  // type support for collectserverptrmap
  typedef collectserverptrmap::iterator iterator;
  typedef collectserverptrmap::const_iterator const_iterator;
  typedef collectserverptrmap::reference reference;
  typedef collectserverptrmap::const_reference const_reference;
  typedef collectserverptrmap::size_type size_type;

  typedef collectserverptrmap::difference_type difference_type;
  typedef collectserverptrmap::const_reverse_iterator const_reverse_iterator;
  typedef collectserverptrmap::reverse_iterator reverse_iterator;
  
  // basic container support
  iterator begin () {return collectserverptrs.begin();}
  const_iterator begin () const {return collectserverptrs.begin();}
  iterator end () {return collectserverptrs.end();}
  const_iterator end () const {return collectserverptrs.end();}

  void erase(iterator pos) {collectserverptrs.erase(pos);}
  void erase(iterator first, iterator last) {collectserverptrs.erase(first, last);}
  collectservermapclass &operator=(const collectservermapclass &x) 
    {collectserverptrs=x.collectserverptrs;return *this;}

  bool empty () const {return collectserverptrs.empty();}
  size_type size() const {return collectserverptrs.size();}


  // added functionality
  void clear () {collectserverptrs.erase(collectserverptrs.begin(),collectserverptrs.end());}

  // thecollectserver remains the property of the calling code but
  // should not be deleted until it is removed from this list.
  void addcollectserver (collectserver *thecollectserver);

  // getcollectserver will return NULL if the collectserver could not be found
  collectserver *getcollectserver (const text_t &collection);
};


#endif
