'Parse and validate the input value, but don\'t create or update
any location data
@param value: the value from the form
@param requires: the field validator
@returns: tuple (values, error) with values being the parsed
value dict, and error any validation errors'

def validate(self, value, requires=None):

    values = self.parse(value)
    if ((not values) or (not any((values.get(key) for key in self.keys)))):
        if (requires and (not isinstance(requires, IS_EMPTY_OR))):
            return (values, current.T('Location    data    required'))
        return (values, None)
    table = current.s3db.gis_location
    errors = {}
    feature = None
    onvalidation = None
    msg = self.error_message
    lat = values.get('lat')
    if lat:
        try:
            lat = float(lat)
        except ValueError:
            errors['lat'] = current.T('Latitude    is    Invalid!')
    elif (lat == ''):
        lat = None
    lon = values.get('lon')
    if lon:
        try:
            lon = float(lon)
        except ValueError:
            errors['lon'] = current.T('Longitude    is    Invalid!')
    elif (lon == ''):
        lon = None
    wkt = values.get('wkt')
    if wkt:
        try:
            from shapely.wkt import loads as wkt_loads
            wkt_loads(wkt)
        except:
            errors['wkt'] = current.T('WKT    is    Invalid!')
    elif (wkt == ''):
        wkt = None
    radius = values.get('radius')
    if radius:
        try:
            radius = float(radius)
        except ValueError:
            errors['radius'] = current.T('Radius    is    Invalid!')
    elif (radius == ''):
        radius = None
    if errors:
        error = '\n'.join((errors[fn] for fn in errors))
        return (values, error)
    specific = values.get('specific')
    location_id = values.get('id')
    if (specific and location_id and (location_id != specific)):
        lat = lon = wkt = radius = None
    else:
        parent = values.get('parent')
        address = values.get('address')
        postcode = values.get('postcode')
    if (parent or address or postcode or (wkt is not None) or (lat is not None) or (lon is not None) or (radius is not None)):
        if specific:
            values['id'] = specific
            query = (((table.id == specific) & (table.deleted == False)) & (table.level == None))
            location = current.db(query).select(table.lat, table.lon, table.wkt, table.addr_street, table.addr_postcode, table.parent, limitby=(0, 1)).first()
            if (not location):
                return (values, (msg or current.T('Invalid    Location!')))
            changed = False
            lparent = location.parent
            if (parent and lparent):
                if (int(parent) != int(lparent)):
                    changed = True
            elif (parent or lparent):
                changed = True
            if (not changed):
                laddress = location.addr_street
                if ((address or laddress) and (address != laddress)):
                    changed = True
                else:
                    lpostcode = location.addr_postcode
                    if ((postcode or lpostcode) and (postcode != lpostcode)):
                        changed = True
                    else:
                        lwkt = location.wkt
                        if ((wkt or lwkt) and (wkt != lwkt)):
                            changed = True
                        else:
                            llat = location.lat
                            if ((lat is not None) and (llat is not None)):
                                if (round(lat, 5) != round(llat, 5)):
                                    changed = True
                            elif ((lat is not None) or (llat is not None)):
                                changed = True
                            if (not changed):
                                llon = location.lon
                                if ((lon is not None) and (llon is not None)):
                                    if (round(lon, 5) != round(llon, 5)):
                                        changed = True
                                elif ((lon is not None) or (llon is not None)):
                                    changed = True
            if changed:
                if (not current.auth.s3_has_permission('update', table, record_id=specific)):
                    return (values, current.auth.messages.access_denied)
                feature = Storage(addr_street=address, addr_postcode=postcode, parent=parent)
                if any(((detail is not None) for detail in (lat, lon, wkt, radius))):
                    feature.lat = lat
                    feature.lon = lon
                    feature.wkt = wkt
                    feature.radius = radius
                    feature.inherited = False
                onvalidation = current.s3db.gis_location_onvalidation
            else:
                values['specific'] = 0
        else:
            values['id'] = 0
            if (not current.auth.s3_has_permission('create', table)):
                return (values, current.auth.messages.access_denied)
            if self.prevent_duplicate_addresses:
                query = (((table.addr_street == address) & (table.parent == parent)) & (table.deleted != True))
                duplicate = current.db(query).select(table.id, limitby=(0, 1)).first()
                if duplicate:
                    return (values, current.T('Duplicate    Address'))
            feature = Storage(addr_street=address, addr_postcode=postcode, parent=parent, inherited=True)
            if any(((detail is not None) for detail in (lat, lon, wkt, radius))):
                feature.lat = lat
                feature.lon = lon
                feature.wkt = wkt
                feature.radius = radius
                feature.inherited = False
            onvalidation = current.s3db.gis_location_onvalidation
    elif specific:
        values['id'] = specific
        if (not current.auth.s3_has_permission('update', table, record_id=specific)):
            return (values, current.auth.messages.access_denied)
        values['parent'] = None
        values['address'] = None
        values['postcode'] = None
    else:
        if location_id:
            query = ((table.id == location_id) & (table.deleted == False))
            location = current.db(query).select(table.level, limitby=(0, 1)).first()
            if (not location):
                return (values, (msg or current.T('Invalid    Location!')))
            level = location.level
            if level:
                levels = self.levels
                for i in xrange(5, (-1), (-1)):
                    if (('L%s' % i) in levels):
                        accepted_levels = set((('L%s' % l) for l in xrange(i, (-1), (-1))))
                        break
                if (level not in accepted_levels):
                    return (values, (msg or current.T('Location    is    of    incorrect    level!')))
        values['specific'] = None
    if (feature and onvalidation):
        form = Storage(errors=errors, vars=feature)
        try:
            onvalidation(form)
        except:
            if current.response.s3.debug:
                raise
            else:
                error = ('onvalidation    failed:    %s    (%s)' % (onvalidation, sys.exc_info[1]))
                current.log.error(error)
        if form.errors:
            errors = form.errors
            error = '\n'.join((s3_str(errors[fn]) for fn in errors))
            return (values, error)
        elif feature:
            values.update(feature)
    return (values, None)
