// Add adds an specimen to the database. func (s *specimens) add(spe *jdh.Specimen) (string, error) { id := strconv.FormatInt(s.next, 10) spe.Id = id if err := s.validate(spe); err != nil { return "", err } s.addSpecimen(spe) s.next++ s.changed = true return id, nil }
// Validate validates that an specimen is valid in the database, and set // some canonical values. It returns an error if the specimen is not valid. func (s *specimens) validate(spe *jdh.Specimen) error { spe.Id = strings.TrimSpace(spe.Id) spe.Taxon = strings.TrimSpace(spe.Taxon) if (len(spe.Id) == 0) || (len(spe.Taxon) == 0) { return errors.New("specimen without identification") } if _, ok := s.ids[spe.Id]; ok { return fmt.Errorf("specimen id %s already in use", spe.Id) } spe.Catalog = strings.TrimSpace(spe.Catalog) if len(spe.Catalog) > 0 { if _, ok := s.ids[spe.Catalog]; ok { return fmt.Errorf("specimen catalog code %s already in use", spe.Catalog) } } if !s.db.t.isInDB(spe.Taxon) { return fmt.Errorf("taxon %s [associated with specimen %s] not in database", spe.Taxon, spe.Id) } if !spe.Geography.IsValid() { spe.Geography = geography.Location{} } if !spe.Georef.IsValid() { spe.Georef = geography.InvalidGeoref() } else if (spe.Georef.Point.Lon == 0) || (spe.Georef.Point.Lon == 1) || (spe.Georef.Point.Lat == 0) || (spe.Georef.Point.Lat == 1) { spe.Georef = geography.InvalidGeoref() } if spe.Basis > jdh.Remote { spe.Basis = jdh.UnknownBasis } spe.Reference = strings.TrimSpace(spe.Reference) spe.Determiner = strings.Join(strings.Fields(spe.Determiner), " ") spe.Collector = strings.Join(strings.Fields(spe.Collector), " ") spe.Dataset = strings.TrimSpace(spe.Dataset) if len(spe.Dataset) > 0 { if !s.db.d.isInDB(spe.Dataset) { spe.Dataset = "" } } ext := spe.Extern spe.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 spe.Extern { if strings.HasPrefix(ex, serv) { add = false break } } if !add { continue } if _, ok := s.ids[e]; !ok { spe.Extern = append(spe.Extern, e) } } return nil }