Example #1
0
// Validate validates that a taxon is valid in the database, and set some
// canonical values. It returns an error if the taxon is not valid.
func (t *taxonomy) validate(tax *jdh.Taxon) error {
	tax.Id = strings.TrimSpace(tax.Id)
	tax.Name = strings.Join(strings.Fields(tax.Name), " ")
	if (len(tax.Id) == 0) || (len(tax.Name) == 0) {
		return errors.New("taxon without identification")
	}
	if _, ok := t.ids[tax.Id]; ok {
		return fmt.Errorf("taxon id %s already in use", tax.Id)
	}
	p := t.root
	if tax.Rank > jdh.Species {
		tax.Rank = jdh.Unranked
	}
	if len(tax.Parent) > 0 {
		var ok bool
		if p, ok = t.ids[tax.Parent]; !ok {
			return fmt.Errorf("taxon %s parent [%s] not in database", tax.Name, tax.Parent)
		}
	}
	if p == t.root {
		if !tax.IsValid {
			return fmt.Errorf("taxon %s is a synonym without a parent", tax.Name)
		}
	} else if !p.data.IsValid {
		return fmt.Errorf("taxon %s parent [%s] is a synonym", tax.Name, p.data.Name)
	}
	if !p.isDescValid(tax.Rank, tax.IsValid) {
		return fmt.Errorf("taxon %s rank incompatible with database hierarchy", tax.Name)
	}
	ext := tax.Extern
	tax.Extern = nil
	for _, e := range ext {
		serv, id, err := jdh.ParseExtern(e)
		if err != nil {
			continue
		}
		if len(id) == 0 {
			continue
		}
		add := true
		for _, ex := range tax.Extern {
			if strings.HasPrefix(ex, serv) {
				add = false
				break
			}
		}
		if !add {
			continue
		}
		if _, ok := t.ids[e]; !ok {
			tax.Extern = append(tax.Extern, e)
		}
	}
	return nil
}
Example #2
0
// Add adds a new taxon to the database.
func (t *taxonomy) add(tax *jdh.Taxon) (string, error) {
	id := strconv.FormatInt(t.next, 10)
	tax.Id = id
	if err := t.validate(tax); err != nil {
		return "", err
	}
	t.addTaxon(tax)
	t.next++
	t.changed = true
	return id, nil
}
Example #3
0
// TxSyncUpdate implements the update option of tx.sync.
func txSyncUpdate(c *cmdapp.Command, tax *jdh.Taxon) {
	// first process the descendants (as it is possible that a taxon
	// will be set as synonym, and then thier descendant set will change)
	l := getTaxDesc(c, localDB, tax.Id, true)
	txSyncUpdateNav(c, l)
	l = getTaxDesc(c, localDB, tax.Id, false)
	txSyncUpdateNav(c, l)

	if len(tax.Id) == 0 {
		return
	}
	eid := searchExtern(extDBFlag, tax.Extern)
	if len(eid) == 0 {
		return
	}
	ext := taxon(c, extDB, eid)
	if len(ext.Id) == 0 {
		fmt.Fprintf(os.Stderr, "unable to retrieve %s:%s\n", tax.Extern, eid)
		return
	}
	if validFlag {
		if tax.IsValid != ext.IsValid {
			args := new(jdh.Values)
			args.Add(jdh.KeyId, tax.Id)
			if ext.IsValid {
				args.Add(jdh.TaxValid, "")
				localDB.Exec(jdh.Set, jdh.Taxonomy, args)
			} else {
				p := taxon(c, localDB, extDBFlag+":"+ext.Parent)
				if len(p.Id) == 0 {
					exPar := taxon(c, extDB, ext.Parent)
					p = txSyncAddToTaxonomy(c, exPar)
				}
				args.Add(jdh.TaxSynonym, p.Id)
				localDB.Exec(jdh.Set, jdh.Taxonomy, args)
			}
		}
	}
	if !updateFlag {
		return
	}
	if len(ext.Authority) > 0 {
		args := new(jdh.Values)
		args.Add(jdh.KeyId, tax.Id)
		args.Add(jdh.TaxAuthority, ext.Authority)
		localDB.Exec(jdh.Set, jdh.Taxonomy, args)
	}
	if ext.Rank != jdh.Unranked {
		args := new(jdh.Values)
		args.Add(jdh.KeyId, tax.Id)
		args.Add(jdh.TaxRank, ext.Rank.String())
		localDB.Exec(jdh.Set, jdh.Taxonomy, args)
	}
	if len(ext.Comment) > 0 {
		if len(tax.Comment) > 0 {
			tax.Comment += "\n"
		}
		tax.Comment += ext.Comment
		args := new(jdh.Values)
		args.Add(jdh.KeyId, tax.Id)
		args.Add(jdh.KeyComment, tax.Comment)
		localDB.Exec(jdh.Set, jdh.Taxonomy, args)
	}
}