def parse_line(self, line):
        """Parses a single line of a GPI.

        Return a tuple `(processed_line, entities)`. Typically
        there will be a single entity, but in some cases there
        may be none (invalid line) or multiple (disjunctive clause in
        annotation extensions)

        Note: most applications will only need to call this directly if they require fine-grained control of parsing. For most purposes,
        :method:`parse_file` can be used over the whole file

        Arguments
        ---------
        line : str
            A single tab-seperated line from a GPAD file

        """
        vals = line.split("\t")

        if len(vals) < 7:
            self.report.error(line, assocparser.Report.WRONG_NUMBER_OF_COLUMNS, "")
            return line, []

        if len(vals) < 10 and len(vals) >= 7:
            missing_columns = 10 - len(vals)
            vals += ["" for i in range(missing_columns)]

        [
            db,
            db_object_id,
            db_object_symbol,
            db_object_name,
            db_object_synonym,
            db_object_type,
            taxon,
            parent_object_id,
            xrefs,
            properties
        ] = vals

        split_line = assocparser.SplitLine(line=line, values=vals, taxon=taxon)

        ## --
        ## db + db_object_id. CARD=1
        ## --
        id = self._pair_to_id(db, db_object_id)
        if not self._validate_id(id, split_line, context=assocparser.Report):
            return line, []

        ## --
        ## db_object_synonym CARD=0..*
        ## --
        synonyms = db_object_synonym.split("|")
        if db_object_synonym == "":
            synonyms = []

        # TODO: DRY
        parents = parent_object_id.split("|")
        if parent_object_id == "":
            parents = []
        else:
            parents = [self._normalize_id(x) for x in parents]
            for p in parents:
                self._validate_id(p, split_line, context=assocparser.Report)

        xref_ids = xrefs.split("|")
        if xrefs == "":
            xref_ids = []

        obj = {
            'id': id,
            'label': db_object_symbol,
            'full_name': db_object_name,
            'synonyms': synonyms,
            'type': db_object_type,
            'parents': parents,
            'xrefs': xref_ids,
            'taxon': {
                'id': self._taxon_id(taxon, split_line)
            }
        }
        return line, [obj]
Parses a single line of a GPI.

        Return a tuple `(processed_line, entities)`. Typically
        there will be a single entity, but in some cases there
        may be none (invalid line) or multiple (disjunctive clause in
        annotation extensions)

        Note: most applications will only need to call this directly if they require fine-grained control of parsing. For most purposes,
        :method:`parse_file` can be used over the whole file

        Arguments
        ---------
        line : str
            A single tab-seperated line from a GPAD file