예제 #1
0
    def validate(self):
        validation_errors = []
        validation_errors += self.validate_mutually_required_fields(
            ['micro_plot_id', 'post', 'stake_type', 'azimuth', 'distance'])

        if None != self.micro_plot_id and self.micro_plot_id not in range(
                1, Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'microplot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        if None != self.post and self.post not in [1, 2]:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'post', '1 or 2',
                                     self.post))

        if None != self.stake_type and self.stake_type not in [
                'Wooden', 'Rebar'
        ]:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'stake type',
                                     'Wooden or Rebar', self.stake_type))

        if None != self.azimuth and (self.azimuth < 0 or self.azimuth > 359):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'azimuth',
                                     '0-359', self.azimuth))

        if None != self.distance and self.distance <= 0:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'distance', '> 0',
                                     self.distance))

        return validation_errors
예제 #2
0
    def validate(self):
        validation_errors = []
        validation_errors += self.validate_mutually_required_fields(
            ['micro_plot_id', 'azimuth_1', 'azimuth_2', 'azimuth_3'])

        if None != self.micro_plot_id and self.micro_plot_id not in range(
                1, Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'micro plot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        if None != self.azimuth_1 and (self.azimuth_1 < 0
                                       or self.azimuth_1 > 359):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'azimuth 1',
                                     '0-359', self.azimuth_1))

        if None != self.azimuth_2 and (self.azimuth_2 < 0
                                       or self.azimuth_2 > 359):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'azimuth 2',
                                     '0-359', self.azimuth_2))

        if None != self.azimuth_3 and (self.azimuth_3 < 0
                                       or self.azimuth_3 > 359):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'azimuth 3',
                                     '0-359', self.azimuth_3))

        return validation_errors
예제 #3
0
    def validate_deer_impact(self, field):
        validation_errors = []
        impact_rating = getattr(self, field)
        impact_notes = getattr(self, f'{field}_notes')
        
        if None != impact_rating:
            if 0 > impact_rating or 5 < impact_rating:
                validation_errors.append(FieldValidationError(self.get_object_type(), f'{field} impact rating', '0-5', impact_rating))

            if None == impact_notes:
                validation_errors.append(FieldValidationError(self.get_object_type(), f'{field} impact notes', 'non-empy', impact_notes))

        return validation_errors
예제 #4
0
    def validate(self):
        validation_errors = []

        if 3 > len(self.witness_trees):
            validation_errors.append(
                FieldCountValidationError(self.get_object_type(),
                                          'witness trees', 'at least 3',
                                          len(self.witness_trees)))

        for i in range(0, 3):
            if i >= len(self.witness_trees):
                continue

            if i + 1 != int(self.witness_trees[i].tree_number):
                validation_errors.append(
                    FieldValidationError(self.get_object_type(),
                                         'witness tree number order',
                                         '1-3 contiguous numbering',
                                         self.witness_trees[i].tree_number))

        if 3 < len(self.witness_trees):
            for i in range(3, len(self.witness_trees)):
                if 0 == i % 2 and 2 != int(self.witness_trees[i].tree_number):
                    validation_errors.append(
                        FieldValidationError(
                            self.get_object_type(),
                            'witness tree number order',
                            '1-2 contiguous numering',
                            self.witness_trees[i].tree_number))
                elif 1 == i % 2 and 1 != int(
                        self.witness_trees[i].tree_number):
                    validation_errors.append(
                        FieldValidationError(
                            self.get_object_type(),
                            'witness tree number order',
                            '1-2 contiguous numering',
                            self.witness_trees[i].tree_number))

        for witness_tree in self.witness_trees:
            validation_errors += witness_tree.validate_attribute_type(
                ['dbh', 'azimuth', 'distance'], numbers.Number)
            validation_errors += witness_tree.validate_attribute_type(
                ['live_or_dead'], str)

            try:
                validation_errors += witness_tree.validate()
            except Exception as e:
                validation_errors.append(
                    FatalExceptionError(self.get_object_type(), e))

        return validation_errors
예제 #5
0
    def validate(self):
        validation_errors = []

        self.species_guess = self.override_species(self.species_guess)
        self.species_known = self.override_species(self.species_known)

        if self.get_species_known() not in Tab.TREE_SPECIES:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species known',
                                     'tree species', self.get_species_known()))

        if None != self.get_species_guess() and self.get_species_guess(
        ) not in Tab.TREE_SPECIES:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species guess',
                                     'tree species', self.get_species_known()))

        if self.micro_plot_id not in range(1,
                                           Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'microplot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        if None == self.species_known:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species known',
                                     'non-empty', self.species_known))

        if None != self.species_known:
            validation_errors += self.validate_species(self.species_known)

        if None != self.species_guess:
            validation_errors += self.validate_species(self.species_guess)

        if None == self.diameter_breast_height:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'dbh',
                                     'non-empty', self.diameter_breast_height))
        else:
            if 5 > self.diameter_breast_height:
                validation_errors.append(
                    FieldValidationError(self.get_object_type(), 'dbh', '> 5',
                                         self.diameter_breast_height))

            if not (self.diameter_breast_height * 10).is_integer():
                validation_errors.append(
                    FieldValidationError(self.get_object_type(), 'dbh',
                                         '0.1 increments',
                                         self.diameter_breast_height))

        if self.live_or_dead not in ['L', 'D']:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'L or D',
                                     'L or D', self.live_or_dead))

        return validation_errors
예제 #6
0
    def validate(self):
        validation_errors = []
        validation_errors += self.validate_mutually_required_fields(
            ['active_exclosure', 'repairs', 'level', 'notes'])

        if None != self.active_exclosure and self.active_exclosure not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(),
                                     'fenced subplot condition',
                                     self.YES_NO_TEXT, self.active_exclosure))

        if None != self.repairs and self.repairs not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'repairs',
                                     self.YES_NO_TEXT, self.repairs))

        if None != self.level and self.level not in range(0, 4):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'level', '0-3',
                                     self.level))

        return validation_errors
예제 #7
0
    def validate(self):
        validation_errors = []
        validation_errors += self.validate_mutually_required_fields(
            ['micro_plot_id', 'repairs', 'level', 'notes'])

        if None != self.micro_plot_id and self.micro_plot_id not in range(
                1, Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'microplot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        if None != self.repairs and self.repairs not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'repairs',
                                     self.YES_NO_TEXT, self.repairs))

        if None != self.level and self.level not in range(0, 4):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'level', '0-3',
                                     self.level))

        return validation_errors
예제 #8
0
    def validate(self):
        validation_errors = []

        self.species_known = self.override_species(self.species_known)
        self.species_guess = self.override_species(self.species_guess)

        if int(self.tree_number) not in range(1, 4):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'tree number',
                                     '1-3', self.tree_number))

        if self.micro_plot_id not in range(1,
                                           Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'micro plot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        if None == self.species_known:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species known',
                                     'non-empty', self.species_known))

        if None != self.species_known:
            validation_errors += self.validate_species(self.species_known)

        if None != self.species_guess:
            validation_errors += self.validate_species(self.species_guess)

        if None == self.dbh or self.dbh < 5:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'DBH', '> 5',
                                     self.dbh))

        if None == self.live_or_dead or self.live_or_dead not in ['L', 'D']:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'live or dead',
                                     'L or D', self.live_or_dead))

        if None == self.azimuth or self.azimuth < 0 or self.azimuth > 359:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'azimuth',
                                     '0-359', self.azimuth))

        if None == self.distance or self.distance < 0:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'distance', '> 0',
                                     self.distance))

        return validation_errors
예제 #9
0
    def validate(self):
        validation_errors = []

        validation_errors += super().validate()

        validation_errors += self.validate_mutually_required_fields(
            ['disturbance', 'disturbance_type', 'lime', 'herbicide'])

        if self.forested not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'forested',
                                     self.YES_NO_TEXT, self.forested))

        if None != self.disturbance and self.disturbance not in [0, 1]:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'disturbance',
                                     '0-1', self.disturbance))

        if 0 == self.disturbance and None == self.disturbance_type:
            self.disturbance_type = 0

        if None != self.disturbance and 0 < self.disturbance:
            if None == self.disturbance_type:
                self.disturbance_type = self.disturbance
                self.disturbance = 1

        if None != self.disturbance and None == self.disturbance_type:
            validation_errors.append(
                FieldValidationError(self.get_object_type(),
                                     'disturbance type', '1-4',
                                     self.disturbance_type))

        if None != self.disturbance_type:
            if None == self.disturbance_type or \
                (1 == self.disturbance and self.disturbance_type not in range(1, 5)) or \
                (0 == self.disturbance and 0 != self.disturbance_type):
                validation_errors.append(
                    FieldValidationError(self.get_object_type(),
                                         'disturbance type', '0-4',
                                         self.disturbance_type))

        if None != self.lime and self.lime not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'lime',
                                     self.YES_NO_TEXT, self.lime))

        if None != self.herbicide and self.herbicide not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'herbicide',
                                     self.YES_NO_TEXT, self.herbicide))

        return validation_errors
예제 #10
0
    def validate(self):
        validation_errors = []

        if self.micro_plot_id not in range(1,
                                           Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'microplot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        validation_errors += self.validate_mutually_required_fields(
            ['collected', 'fenced', 'azimuth', 'distance'])

        if None != self.collected and self.collected not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'collected',
                                     self.YES_NO_TEXT, self.collected))

        if None != self.re_monumented and self.re_monumented not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'remonumented',
                                     self.YES_NO_TEXT, self.re_monumented))

        if None != self.fenced and self.fenced not in self.YES_NO_RESPONSE:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'fenced',
                                     self.YES_NO_TEXT, self.fenced))

        if None != self.azimuth and (self.azimuth < 0 or self.azimuth > 365):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'azimuth',
                                     '0-365', self.azimuth))

        if None != self.distance and self.distance <= 0:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'distance',
                                     '> 0 feet', self.distance))

        return validation_errors
예제 #11
0
    def validate(self):
        validation_errors = []

        self.species_known = self.override_species(self.species_known)
        self.species_guess = self.override_species(self.species_guess)

        if self.micro_plot_id not in range(1, Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(FieldValidationError(self.get_object_type(), 'microplot ID', f'1-{Validatable.MAX_MICRO_PLOT_ID}', self.micro_plot_id))

        if self.quarter not in range(1, 5):
            validation_errors.append(FieldValidationError(self.get_object_type(), 'quarter', '1-4', self.quarter))

        self.scale = self.override_scale(self.scale)

        if self.scale not in [300, 1000]:
            validation_errors.append(FieldValidationError(self.get_object_type(), 'scale', '300 or 1000', self.scale))

        if None == self.species_known:
            validation_errors.append(FieldValidationError(self.get_object_type(), 'species known', 'non-empty', self.species_known))

        if None != self.species_known:
            validation_errors += self.validate_species(self.species_known)

        if None != self.species_guess:
            validation_errors += self.validate_species(self.species_guess)

        if self.get_species_known() not in Validatable.COVER_SPECIES:
            validation_errors.append(FieldValidationError(self.get_object_type(), 'species known', 'cover species', self.get_species_known()))

        if None != self.get_species_guess() and self.get_species_guess() not in Validatable.COVER_SPECIES:
            validation_errors.append(FieldValidationError(self.get_object_type(), 'species guess', 'cover species', self.get_species_guess()))

        if self.percent_cover not in range(0, 10):
            validation_errors.append(FieldValidationError(self.get_object_type(), f'percent cover of species {self.species_known}', '0-9', self.percent_cover))

        if self.species_known not in (CoverSpecies.HEIGHT_OPTIONAL_SPECIES + Tab.TREE_SPECIES) and self.average_height not in range(1, 6):
            validation_errors.append(FieldValidationError(self.get_object_type(), f'average height of species {self.species_known}', '1-5', self.average_height))

        if None != self.flower:
            if self.flower % 1 != 0:
                validation_errors.append(FieldValidationError(self.get_object_type(), f'flower of species {self.species_known}', 'integer value', self.flower))

            self.flower = int(self.flower)

        if self.species_known in CoverSpecies.DEER_INDICATOR_SPECIES:
            if None == self.count:
                validation_errors.append(FieldValidationError(self.get_object_type(), 'count of species {}'.format(self.species_guess or self.species_known), 'non-empty', self.count))
            elif 0 == self.count:
                validation_errors.append(FieldValidationError(self.get_object_type(), 'count of species {}'.format(self.species_guess or self.species_known), 'non-zero', self.count))

            if None == self.flower:
                validation_errors.append(FieldValidationError(self.get_object_type(), 'count of flowering for species {}'.format(self.species_guess or self.species_known), 'non-empty', self.flower))

        if self.species_known not in CoverSpecies.TRILLIUM_SPECIES and None != self.number_of_stems:
            validation_errors.append(FieldValidationError(self.get_object_type(), 'nstem', 'empty for non-trillium species', self.number_of_stems))

        if self.species_known in CoverSpecies.TRILLIUM_SPECIES and None == self.number_of_stems:
            self.number_of_stems = 0

        return validation_errors
예제 #12
0
    def validate(self):
        validation_errors = []

        if self.study_area not in range(1, 5):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'study area',
                                     '1-4', self.study_area))

        if self.plot_number not in range(1, 51):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'plot number',
                                     '1-50', self.plot_number))

        if self.deer_impact not in range(0, 6):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'deer impact',
                                     '0-5', self.deer_impact))

        if None == self.collection_date:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'collection date',
                                     'a date', 'None'))

        if not self.subplots:
            validation_errors.append(
                FieldCountValidationError('General Tab', 'subplots',
                                          Validatable.MAX_MICRO_PLOT_ID,
                                          'None'))

        if Validatable.MAX_MICRO_PLOT_ID != len(self.subplots):
            validation_errors.append(
                FieldCountValidationError('General Tab', 'subplots',
                                          Validatable.MAX_MICRO_PLOT_ID,
                                          len(self.subplots)))

        micro_plot_id_list = []
        for subplot in self.subplots:
            validation_errors += subplot.validate()
            micro_plot_id_list.append(subplot.micro_plot_id)

        if set(micro_plot_id_list) != set(
                range(1, Validatable.MAX_MICRO_PLOT_ID + 1)):
            validation_errors.append(
                MissingSubplotValidationError(self.get_object_type(),
                                              micro_plot_id_list))

        last_post_number = None
        for auxillary_post_location in self.auxillary_post_locations:
            validation_errors += auxillary_post_location.validate()

            if None == last_post_number and 1 != auxillary_post_location.post:
                validation_errors.append(
                    FieldValidationError('Auxillary Post Location',
                                         'Post number', 1,
                                         auxillary_post_location.post))
            elif 1 == last_post_number and 2 != auxillary_post_location.post:
                validation_errors.append(
                    FieldValidationError('Auxillary Post Location',
                                         'Post number', 2,
                                         auxillary_post_location.post))
            elif 2 == last_post_number and 1 != auxillary_post_location.post:
                validation_errors.append(
                    FieldValidationError('Auxillary Post Location',
                                         'Post number', 1,
                                         auxillary_post_location.post))

            last_post_number = auxillary_post_location.post

        for non_forested_azimuth in self.non_forested_azimuths:
            validation_errors += non_forested_azimuth.validate()

        return validation_errors
예제 #13
0
    def validate(self):
        validation_errors = []

        self.species_guess = self.override_species(self.species_guess)
        self.species_known = self.override_species(self.species_known)

        if self.get_species_known() not in Validatable.SEEDLING_SPECIES:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species known',
                                     'seedling species',
                                     self.get_species_known()))

        if None != self.get_species_guess() and self.get_species_guess(
        ) not in Validatable.SEEDLING_SPECIES:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species guess',
                                     'seedling species',
                                     self.get_species_guess()))

        if self.micro_plot_id not in range(1,
                                           Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'microplot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        if self.quarter not in range(1, 5):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'quarter', '1-4',
                                     self.quarter))

        self.scale = self.override_scale(self.scale)
        if self.scale not in [300, 1000]:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'scale',
                                     '300 or 1000', self.scale))

        if None == self.species_known:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species known',
                                     'non-empty', self.species_known))

        if None != self.species_known:
            validation_errors += self.validate_species(self.species_known)

        if None != self.species_guess:
            validation_errors += self.validate_species(self.species_guess)

        if self.sprout not in [0, 1]:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'sprout',
                                     '0 or 1', self.sprout))

        if None != self.zero_six_inches and 0 > self.zero_six_inches:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), '0-6"', '>= 0',
                                     self.zero_six_inches))

        if None != self.six_twelve_inches and 0 > self.six_twelve_inches:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), '6-12"', '>= 0',
                                     self.six_twelve_inches))

        if None != self.one_three_feet_total and 0 > self.one_three_feet_total:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), "1-3' Total",
                                     '>= 0', self.one_three_feet_total))

        if None != self.one_three_feet_browsed and 0 > self.one_three_feet_browsed:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), "1-3' Browsed",
                                     '>= 0', self.one_three_feet_browsed))

        if None == self.one_three_feet_total and None != self.one_three_feet_browsed:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), "1-3' Browsed",
                                     'empty if Total is empty',
                                     self.one_three_feet_browsed))

        if None != self.one_three_feet_browsed and None != self.one_three_feet_total:
            if self.one_three_feet_browsed > self.one_three_feet_total:
                validation_errors.append(
                    FieldValidationError(self.get_object_type(),
                                         "1-3' Browsed'", "<= 1-3' Total",
                                         self.one_three_feet_browsed))

        if None != self.three_five_feet_total and 0 > self.three_five_feet_total:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), "3-5' Total",
                                     '>= 0', self.three_five_feet_total))

        if None != self.three_five_feet_browsed and 0 > self.three_five_feet_browsed:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), "3-5' Browsed",
                                     '>= 0', self.three_five_feet_browsed))

        if None == self.three_five_feet_total and None != self.three_five_feet_browsed:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), "3-5' Browsed",
                                     'empty if Total is empty',
                                     self.three_five_feet_browsed))

        if None != self.three_five_feet_browsed and None != self.three_five_feet_total:
            if self.three_five_feet_browsed > self.three_five_feet_total:
                validation_errors.append(
                    FieldValidationError(self.get_object_type(),
                                         "3-5' Browsed", "<= 3-5' Total",
                                         self.one_three_feet_browsed))

        if None != self.greater_five_feet_total and 0 > self.greater_five_feet_total:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), ">5' Total",
                                     '>= 0', self.greater_five_feet_total))

        if None != self.greater_five_feet_browsed and 0 > self.greater_five_feet_browsed:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), ">5' Browsed",
                                     '>= 0', self.greater_five_feet_browsed))

        if None == self.greater_five_feet_total and None != self.greater_five_feet_browsed:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), ">5' Browsed",
                                     'empty if Total is empty',
                                     self.three_five_feet_browsed))

        if None != self.greater_five_feet_browsed and None != self.greater_five_feet_total:
            if self.greater_five_feet_browsed > self.greater_five_feet_total:
                validation_errors.append(
                    FieldValidationError(self.get_object_type(), ">5' Browsed",
                                         "<= >5' Total",
                                         self.greater_five_feet_browsed))

        return validation_errors
예제 #14
0
    def validate(self):
        validation_errors = []
        self.species_known = self.override_species(self.species_known)
        self.species_guess = self.override_species(self.species_guess)

        sapling_species = Tab.TREE_SPECIES.copy()
        sapling_species.remove('snag')

        if self.get_species_known() not in sapling_species:
            validation_errors.append(
                FieldValidationError(self.get_object_type(),
                                     'species known', 'sapling species',
                                     self.get_species_known()))

        if None != self.get_species_guess() and self.get_species_guess(
        ) not in sapling_species:
            validation_errors.append(
                FieldValidationError(self.get_object_type(),
                                     'species guess', 'sapling species',
                                     self.get_species_known()))

        if self.micro_plot_id not in range(1,
                                           Validatable.MAX_MICRO_PLOT_ID + 1):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'microplot ID',
                                     f'1-{Validatable.MAX_MICRO_PLOT_ID}',
                                     self.micro_plot_id))

        if self.quarter not in range(1, 5):
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'quarter', '1-4',
                                     self.quarter))

        self.scale = self.override_scale(self.scale)
        if self.scale not in [300, 1000]:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'scale',
                                     '300 or 1000', self.scale))

        if None == self.species_known:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'species known',
                                     'non-empty', self.species_known))

        if None != self.species_known:
            validation_errors += self.validate_species(self.species_known)

        if None != self.species_guess:
            validation_errors += self.validate_species(self.species_guess)

        if None == self.diameter_breast_height:
            validation_errors.append(
                FieldValidationError(self.get_object_type(), 'dbh',
                                     'non-empty', self.diameter_breast_height))
        else:
            if (1 > self.diameter_breast_height) or (
                    5 <= self.diameter_breast_height):
                validation_errors.append(
                    FieldValidationError(self.get_object_type(), 'dbh',
                                         '>= 1 or < 5',
                                         self.diameter_breast_height))

            if not (self.diameter_breast_height * 10).is_integer():
                validation_errors.append(
                    FieldValidationError(self.get_object_type(), 'dbh',
                                         '0.1 increments',
                                         self.diameter_breast_height))

        return validation_errors