'Validate this item (=record onvalidation), sets self.accepted'

def validate(self):

    data = self.data
    if (self.accepted is not None):
        return self.accepted
    if ((data is None) or (not self.table)):
        self.accepted = False
        return False
    xml = current.xml
    ERROR = xml.ATTRIBUTE['error']
    METHOD = self.METHOD
    DELETE = METHOD.DELETE
    MERGE = METHOD.MERGE
    if (not self.id):
        self.deduplicate()
    if (self.accepted is False):
        return False
    if (self.skip or (self.method in (DELETE, MERGE))):
        self.accepted = (True if self.id else False)
        return True
    if (not self.id):
        self._dynamic_defaults(data)
    required_fields = self._mandatory_fields()
    all_fields = data.keys()
    failed_references = []
    items = self.job.items
    for reference in self.references:
        resolvable = resolved = True
        entry = reference.entry
        if (entry and (not entry.id)):
            if entry.item_id:
                item = items[entry.item_id]
                if item.error:
                    relement = reference.element
                    if (relement is not None):
                        msg = ';    '.join(xml.collect_errors(entry.element))
                        relement.set(ERROR, msg)
                    else:
                        resolvable = False
                    resolved = False
            else:
                resolvable = resolved = False
        field = reference.field
        if isinstance(field, (tuple, list)):
            field = field[1]
        if resolved:
            all_fields.append(field)
        elif resolvable:
            if (field not in required_fields):
                required_fields.append(field)
            if (field not in failed_references):
                failed_references.append(field)
    missing = [fname for fname in required_fields if (fname not in all_fields)]
    original = self.original
    if missing:
        if original:
            missing = [fname for fname in missing if (fname not in original)]
        if missing:
            fields = [f for f in missing if (f not in failed_references)]
            if fields:
                errors = [('%s:    value(s)    required' % ',    '.join(fields))]
            else:
                errors = []
            if failed_references:
                fields = ',    '.join(failed_references)
                errors.append(('%s:    reference    import(s)    failed' % ',    '.join(failed_references)))
            self.error = ';    '.join(errors)
            self.element.set(ERROR, self.error)
            self.accepted = False
            return False
    form = Storage(method=self.method, vars=data, request_vars=data)
    if self.id:
        form.vars.id = self.id
    form.errors = Storage()
    tablename = self.tablename
    key = ('%s_onvalidation' % self.method)
    get_config = current.s3db.get_config
    onvalidation = get_config(tablename, key, get_config(tablename, 'onvalidation'))
    if onvalidation:
        try:
            callback(onvalidation, form, tablename=tablename)
        except Exception as e:
            from traceback import format_exc
            current.log.error(('S3Import    %s    onvalidation    exception:' % tablename))
            current.log.debug(format_exc(10))
    accepted = True
    if form.errors:
        element = self.element
        for k in form.errors:
            e = element.findall(("data[@field='%s']" % k))
            if (not e):
                e = element.findall(("reference[@field='%s']" % k))
            if (not e):
                e = element
                form.errors[k] = ('[%s]    %s' % (k, form.errors[k]))
            else:
                e = e[0]
            e.set(ERROR, str(form.errors[k]).decode('utf-8'))
        self.error = current.ERROR.VALIDATION_ERROR
        accepted = False
    self.accepted = accepted
    return accepted
