# File lib/qbxml/request.rb, line 72
    def initialize(object, type, options_or_regexp={})
      options = options_or_regexp.is_a?(Regexp) ? {:matches => options_or_regexp} : options_or_regexp
      @type = type
      raise ArgumentError, "Qbxml::Requests can only be of one of the following types: :query, :transaction, :any_transaction, :mod, :add, :delete, :deleted, or :report" unless @type.is_one_of?(:query, :transaction, :any_transaction, :mod, :report, :add, :delete, :deleted)
      @klass = object.is_a?(Class) ? object : object.class
      @object = object
      @options = options

      # Transform the options received for :deleted requests.
      # This way, Request.new(Customer, :deleted) == Request.new(ListDeleted, :list_del_type => 'Customer')
      # and Request.new(Transaction, :deleted) == Request.new(TxnDeleted, :txn_del_type => 'Transaction')
      if @type == :deleted
        case @klass.ListOrTxn
        when 'List'
          @options[:list_del_type] = @klass.lone_name
          @klass = Quickbooks::ListDeleted
        when 'Txn'
          @options[:txn_del_type] = @klass.lone_name
          @klass = Quickbooks::TxnDeleted
        end
      end

      # Return only specific properties: Request.new(Customer, :query, :only => [:list_id, :full_name]); Quickbooks::Customer.first(:only => :list_id)
      @ret_elements = @options.delete(:only).to_a.only(@klass.properties).ordered(@klass.properties).stringify_values.camelize_values!(Quickbooks::CAMELIZE_EXCEPTIONS) if @options.has_key?(:only)

      # Includes only valid filters + aliases for valid filters, # => {underscore/slashed keys + aliases}
      # then transforms aliased filters to real filters, # => {underscore/slashed keys}
      # then camelizes keys to prepare for writing to XML, # => {}
      # lastly orders the keys to a valid filter order.

      # Study the following:
      #   @klass.filter_aliases = {'deleted_after' => 'deleted_date_range_filter/from_deleted_date'}
      #   @klass.valid_filters = ['deleted_date_range_filter/from_deleted_date']
      #   {:deleted_after => "2008-03-20T11:20:26-04:00"}.slashed.
      #     only(@klass.valid_filters + @klass.filter_aliases.slashed.flat.keys).
      #     transform_keys!(@klass.filter_aliases.slashed.flat).
      #     slash_camelize_keys!(Quickbooks::CAMELIZE_EXCEPTIONS).slashed.
      #     ordered!(@klass.camelized_valid_filters).slashed.expand
      #   # => {"DeletedDateRangeFilter" => {"FromDeletedDate" => "2008-03-20T11:20:26-04:00"}}
      @filters = @options.delete(:filters) || @options.slashed.
        only(@klass.valid_filters + @klass.filter_aliases.slashed.flat.keys).
        transform_keys!(@klass.filter_aliases.slashed.flat).
        slash_camelize_keys!(Quickbooks::CAMELIZE_EXCEPTIONS).
        ordered!(@klass.camelized_valid_filters)
      @filters = @filters.to_hash unless @filters.is_a?(Hash)
      @filters = @filters['FILTERS'] if @filters.keys == ['FILTERS'] # So if you include an xml-formatted string of filters, you can simply wrap them in <FILTERS></FILTERS> as a root key

      # Complain if:
      #   1) type is :mod or :delete, and object supplied is not a valid model
      raise ArgumentError, "A Quickbooks record object must be supplied to perform an add, mod or del action" if @type.is_one_of?(:add, :mod, :delete) && !@object.is_a?(Quickbooks::Base)
    end