'Run the onvalidation callbacks for the master table
and all subtables in the form, and store any errors
in the form.
@param form: the form'

def validate(self, form):

    s3db = current.s3db
    config = self._config
    if self.record_id:
        onvalidation = config('update_onvalidation', config('onvalidation', None))
    else:
        onvalidation = config('create_onvalidation', config('onvalidation', None))
    if (onvalidation is not None):
        try:
            callback(onvalidation, form, tablename=self.tablename)
        except:
            error = ('onvalidation    failed:    %s' % str(onvalidation))
            current.log.error(error)
            raise
    get_config = s3db.get_config
    for alias in self.subtables:
        subdata = self._extract(form, alias)
        if (not subdata):
            continue
        subtable = self.resource.components[alias].table
        subform = Storage(vars=subdata, errors=Storage())
        rows = self.subrows
        if ((alias in rows) and (rows[alias] is not None)):
            pkey = subtable._id
            subform.vars[pkey.name] = rows[alias][pkey]
            subonvalidation = get_config(subtable._tablename, 'update_onvalidation', get_config(subtable._tablename, 'onvalidation', None))
        else:
            subonvalidation = get_config(subtable._tablename, 'create_onvalidation', get_config(subtable._tablename, 'onvalidation', None))
        if (subonvalidation is not None):
            try:
                callback(subonvalidation, subform, tablename=subtable._tablename)
            except:
                error = ('onvalidation    failed:    %s' % str(subonvalidation))
                current.log.error(error)
                raise
            for fn in subform.errors:
                dummy = ('sub_%s_%s' % (alias, fn))
                form.errors[dummy] = subform.errors[fn]
    for component in self.components:
        if hasattr(component, 'validate'):
            component.validate(form)
    return
