# File lib/rbot/messagemapper.rb, line 192
    def recognize(m)
      components = m.message.split(/\s+/)
      options = {}

      @items.each do |item|
        if /^\*/ =~ item.to_s
          if components.empty?
            value = @defaults.has_key?(item) ? @defaults[item].clone : []
          else
            value = components.clone
          end
          components = []
          def value.to_s() self.join(' ') end
          options[item.to_s.sub(/^\*/,"").intern] = value
        elsif item.kind_of? Symbol
          value = components.shift || @defaults[item]
          if passes_requirements?(item, value)
            options[item] = value
          else
            if @defaults.has_key?(item)
              options[item] = @defaults[item]
              # push the test-failed component back on the stack
              components.unshift value
            else
              return nil, requirements_for(item)
            end
          end
        else
          return nil, "No value available for component #{item.inspect}" if components.empty?
          component = components.shift
          return nil, "Value for component #{item.inspect} doesn't match #{component}" if component != item
        end
      end

      return nil, "Unused components were left: #{components.join '/'}" unless components.empty?

      return nil, "template is not configured for private messages" if @options.has_key?(:private) && !@options[:private] && m.private?
      return nil, "template is not configured for public messages" if @options.has_key?(:public) && !@options[:public] && !m.private?

      options.delete_if {|k, v| v.nil?} # Remove nil values.
      return options, nil
    end