// 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 }
// 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 }