'Apply CRUD methods
@param r: the S3Request
@param attr: dictionary of parameters for the method handler
@return: output object to send to the view
Known means of communicating with this module:
It expects a URL of the form: /prefix/name/import
It will interpret the http requests as follows:
GET     will trigger the upload
POST    will trigger either commits or display the import details
DELETE  will trigger deletes
It will accept one of the following control vars:
item:   to specify a single item in the import job
job:    to specify a job
It should not receive both so job takes precedent over item
For CSV imports, the calling controller can add extra fields
to the upload form to add columns to each row in the CSV. To add
the extra fields, pass a named parameter "csv_extra_fields" to the
s3_rest_controller call (or the S3Request call, respectively):
s3_rest_controller(module, resourcename,
csv_extra_fields=[
dict(label="ColumnLabelInTheCSV",
field=field_instance)
The Field instance "field" will be added to the upload form, and
the user input will be added to each row of the CSV under the
label as specified. If the "field" validator has options, the
input value will be translated into the option representation,
otherwise the value will be used as-is.
Note that the "label" in the dict is the column label in the CSV,
whereas the field label for the form is to be set in the Field
instance passed as "field".
You can add any arbitrary number of csv_extra_fields to the list.
Additionally, you may want to allow the user to choose whether
the import shall first remove all existing data in the target
table. To do so, pass a label for the "replace_option" to the
request:
s3_rest_controller(module, resourcename,
replace_option=T("Remove existing data before import"))
This will add the respective checkbox to the upload form.
You may also want to provide a link to download a CSV template from
the upload form. To do that, add the resource name to the request
attributes:
s3_rest_controller(module, resourcename,
csv_template="<resourcename>")
This will provide a link to:
- static/formats/s3csv/<controller>/<resourcename>.csv
at the top of the upload form.'

def apply_method(self, r, **attr):

    T = current.T
    messages = self.messages = Messages(T)
    messages.download_template = 'Download    Template'
    messages.invalid_file_format = 'Invalid    File    Format'
    messages.unsupported_file_type = 'Unsupported    file    type    of    %s'
    messages.stylesheet_not_found = 'No    Stylesheet    %s    could    be    found    to    manage    the    import    file.'
    messages.no_file = 'No    file    submitted'
    messages.file_open_error = 'Unable    to    open    the    file    %s'
    messages.file_not_found = 'The    file    to    upload    is    missing'
    messages.no_records_to_import = 'No    records    to    import'
    messages.no_job_to_delete = 'No    job    to    delete,    maybe    it    has    already    been    deleted.'
    messages.title_job_read = 'Details    of    the    selected    import    job'
    messages.title_job_list = 'List    of    import    items'
    messages.file_uploaded = 'Import    file    uploaded'
    messages.upload_submit_btn = 'Upload    Data    File'
    messages.open_btn = 'Open'
    messages.view_btn = 'View'
    messages.delete_btn = 'Delete'
    messages.item_show_details = 'Display    Details'
    messages.job_total_records = 'Total    records    in    the    Import    Job'
    messages.job_records_selected = 'Records    selected'
    messages.job_deleted = 'Import    job    deleted'
    messages.job_completed = 'Job    run    on    %s.    With    result    of    (%s)'
    messages.import_file = 'Import    File'
    messages.import_file_comment = 'Upload    a    file    formatted    according    to    the    Template.'
    messages.user_name = 'User    Name'
    messages.commit_total_records_imported = '%s    records    imported'
    messages.commit_total_records_ignored = '%s    records    ignored'
    messages.commit_total_errors = '%s    records    in    error'
    tablename = self.tablename
    self.__define_table()
    permitted = current.auth.s3_has_permission
    authorised = (permitted('create', self.upload_tablename) and permitted('create', tablename))
    if (not authorised):
        if (r.method is not None):
            r.unauthorised()
        else:
            return dict(form=None)
    self.controller_resource = self.resource
    self.controller_table = self.table
    self.controller_tablename = tablename
    self.upload_resource = None
    self.item_resource = None
    self.controller = r.controller
    self.function = r.function
    try:
        self.uploadTitle = (current.response.s3.crud_strings[tablename].title_upload or T('Import'))
    except:
        self.uploadTitle = T('Import')
    current.session.s3.ocr_enabled = False
    self.error = None
    self.warning = None
    if ('csv_stylesheet' in attr):
        self.csv_stylesheet = attr['csv_stylesheet']
    else:
        self.csv_stylesheet = None
    self.csv_extra_fields = None
    self.csv_extra_data = None
    self.xslt_path = os.path.join(r.folder, r.XSLT_PATH)
    self.xslt_extension = r.XSLT_EXTENSION
    transform = r.get_vars.get('transform', None)
    source = r.get_vars.get('filename', None)
    if ('job' in r.post_vars):
        upload_id = r.post_vars['job']
    elif ('job' in r.get_vars):
        upload_id = r.get_vars['job']
    else:
        upload_id = None
    items = self._process_item_list(upload_id, r.vars)
    if ('delete' in r.get_vars):
        r.http = 'DELETE'
    self.upload_id = upload_id
    query = (self.upload_table.id == upload_id)
    self.upload_job = current.db(query).select(limitby=(0, 1)).first()
    if self.upload_job:
        self.job_id = self.upload_job.job_id
    else:
        self.job_id = None
    self.ajax = (current.request.ajax and (r.post_vars.approach == 'ajax'))
    if (r.http == 'GET'):
        if (source != None):
            self.commit(source, transform)
            output = self.upload(r, **attr)
        if (upload_id != None):
            output = self.display_job(upload_id)
        else:
            output = self.upload(r, **attr)
    elif (r.http == 'POST'):
        if (items != None):
            output = self.commit_items(upload_id, items)
        else:
            output = self.generate_job(r, **attr)
    elif (r.http == 'DELETE'):
        if (upload_id != None):
            output = self.delete_job(upload_id)
    else:
        r.error(405, current.ERROR.BAD_METHOD)
    return output
