//=-- AccessFormatPlugin.h - Transform a line of text into a parsed structure -=
//
//  This class is used to handle one line out of the access_log file, and 
//  convert into a more accessable and useful form.  Different subclasses are
//  used to implement the parsing functionality.
//
//=----------------------------------------------------------------------------=
//  This file is copyright (c) 1997-2000 Chris Lattner
//=----------------------------------------------------------------------------=

#ifndef ACCESS_FORMAT_PLUGIN_H
#define ACCESS_FORMAT_PLUGIN_H

#include "Plugin.h"
class String;
class Date;

class MSAPI AccessFormatPlugin : public Plugin {
public :
  AccessFormatPlugin(const String &name) : Plugin(name) {}
  virtual ~AccessFormatPlugin() {}

  virtual PluginType GetType() const { return GetPluginType(); }

  inline static PluginType GetPluginType() { 
    return Plugin::ACCESS_FORMAT_PLUGIN; 
  }

  // Provide a convenient way to create AccessLogPlugin objects...
  static AccessFormatPlugin *CreatePlugin(const String &Name) {
    return (AccessFormatPlugin *)Plugin::CreatePlugin(
                                     Plugin::ACCESS_FORMAT_PLUGIN, Name);
  }

  // Provide a way to index through all of the available plugins, looking for a
  // plugin that will recognize the specified line of a log file...
  //
  static AccessFormatPlugin *SelectPlugin(const String &Line) {
    return (AccessFormatPlugin *)Plugin::CreatePlugin(GetPluginType(), 
                                                      (void*)&Line);
    }

  // SetDomain - Specify the domain for the entire log file... useful if the 
  // log lines do not contain domain information in them...
  //
  virtual void SetDomain(const String &Domain) = 0;

  virtual void SetAccessLogFilename(const String &FN) = 0;
  virtual String GetAccessLogFilename() const = 0;

  virtual int ParseAccess(String &) = 0;
  virtual ostream &print(ostream &o = cout) const;
  int Compare(const Object &L) const;

  virtual void operator=(const AccessFormatPlugin &F) = 0;


  // Field Codes...
  enum {
    FEHost     = 1,
    FEAuth     = 2,
    FEDate     = 3,
    FEType     = 4,
    FEURL      = 5,
    FEProtocol = 6,
    FEStatus   = 7,
    FESize     = 8,
    FEDomain   = 9,
    FEReferrer = 10,
    FEBrowser  = 11
  };

  virtual const String &GetField(int FieldNo) const;
  virtual void SetField(int FieldNo, const String &FieldVal);
  static int GetFieldID(const CSString &FieldName);

  virtual const String &GetHost()       const = 0;   // Host
  virtual       String &GetHost()             = 0;
  virtual const String &GetAuth()       const = 0;   // Auth
  virtual       String &GetAuth()             = 0;
  virtual const Date   &GetDate()       const = 0;   // Date
  virtual       Date   &GetDate()             = 0;
  virtual const String &GetRetType()    const = 0;   // Retrieval type Ex: GET
  virtual       String &GetRetType()          = 0;
  virtual const String &GetURL()        const = 0;   // Requested URL
  virtual       String &GetURL()              = 0;
  virtual const String &GetProtocol()   const = 0;   // Protocol
  virtual       String &GetProtocol()         = 0;
  virtual const String &GetDomain()     const = 0;   // Domain
  virtual       String &GetDomain()           = 0;
  virtual const String &GetReferrer()   const = 0;   // URL of Referrer
  virtual       String &GetReferrer()         = 0;
  virtual const String &GetBrowser()    const = 0;   // Browser String
  virtual       String &GetBrowser()          = 0;

  virtual       int     GetStatusCode() const = 0;   // Status code
  virtual       void    SetStatusCode(int S)  = 0;
  virtual       int     GetLength()     const = 0;   // File length, or 0
  virtual       void    SetLength(int L)      = 0;

protected:
  int ParseDateString(String &TimeInfo);
};


// Template AccessFormatPluginImpl class:
//
// Implementation tool for implementing AccessFormatPlugin classes.  This 
// defines functions that call the plugin's constructor...
//
template <class SubClass>
class AccessFormatPluginImpl 
             : public PluginTemplate<AccessFormatPlugin,SubClass> {
public :

  // CreateInstanceData - Specify how to create a plugin when instance data
  // is present.
  static Plugin *CreateInstanceData(void *Data) {
    const String &ExampleLine = *(const String *)Data;
    int CreateError = 0;

    SubClass *P = new SubClass(ExampleLine, CreateError);
    if (CreateError) {
      delete P;
      return 0;
    }

    return P;
  }

  // By default, AccessFormatPlugin specify their priority.  The default value,
  // which should probably be overriden, is 1000, the lowest priority.
  inline static int GetPriority() { return 1000; }



  virtual void SetAccessLogFilename(const String &Arg) {
    ALFilename = Arg;
  }
  virtual String GetAccessLogFilename() const { return ALFilename; }

private:
  String ALFilename;
};


#endif
