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

        # Detect update
        if not self.id:
            self.deduplicate()
        if self.accepted is False:
            # Item rejected by deduplicator (e.g. due to ambiguity)
            return False

        # Don't need to validate skipped or deleted records
        if self.skip or self.method in (DELETE, MERGE):
            self.accepted = True if self.id else False
            return True

        # Set dynamic defaults for new records
        if not self.id:
            self._dynamic_defaults(data)

        # Check for mandatory fields
        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:
                            # Repeat the errors from the referenced record
                            # in the <reference> element (better reasoning)
                            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:
                # Both reference and referenced record are in the XML,
                # => treat foreign key as mandatory, and mark as failed
                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

        # Run onvalidation
        form = Storage(method = self.method,
                       vars = data,
                       request_vars = data,
                       # Useless since always incomplete:
                       #record = original,
                       )
        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, 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

    # -------------------------------------------------------------------------
Validate this item (=record onvalidation), sets self.accepted
dataset/ETHPy150Open sahana/eden/modules/s3/s3import.py/S3ImportItem.validate