Example #1
0
func (o *occurrence) copy() *jdh.Specimen {
	cat := strings.TrimSpace(o.InstitutionCode)
	cat += ":" + strings.TrimSpace(o.CollectionCode)
	cat += ":" + strings.TrimSpace(o.CatalogNumber)
	t, _ := time.Parse("2006-01-02T15:04:05.000-0700", o.OccurrenceDate)
	spe := &jdh.Specimen{
		Id:         strconv.FormatInt(o.Key, 10),
		Taxon:      strconv.FormatInt(o.TaxonKey, 10),
		Basis:      getBasis(o.BasisOfRecord),
		Dataset:    strings.TrimSpace(o.DatasetKey),
		Catalog:    cat,
		Determiner: strings.Join(strings.Fields(o.IdentifierName), " "),
		Collector:  strings.Join(strings.Fields(o.CollectorName), " "),
		Date:       t,
		Geography: geography.Location{
			Country: geography.GetCountry(o.CountryCode),
			State:   strings.Join(strings.Fields(o.StateProvince), " "),
			County:  strings.Join(strings.Fields(o.County), " "),
		},
		Locality: strings.Join(strings.Fields(o.Locality), " "),
		Comment:  strings.TrimSpace(o.FieldNotes + "\n" + o.OccurrenceRemarks),
	}
	if (len(spe.Locality) == 0) && (len(o.VerbatimLocality) > 0) {
		spe.Locality = strings.Join(strings.Fields(o.VerbatimLocality), " ")
	}
	lon, lat := float64(360), float64(360)
	if o.DecimalLongitude != 0 {
		lon = o.DecimalLongitude
	}
	if o.DecimalLatitude != 0 {
		lat = o.DecimalLatitude
	}
	if geography.IsLon(lon) && geography.IsLat(lat) {
		spe.Georef.Point = geography.Point{Lon: lon, Lat: lat}
		spe.Georef.Source = strings.Join(strings.Fields(o.GeoreferenceSources), " ")
	} else {
		spe.Georef = geography.InvalidGeoref()
	}
	return spe
}
Example #2
0
// Set sets a value of an specimen in the database.
func (s *specimens) set(vals []jdh.KeyValue) error {
	id := ""
	for _, kv := range vals {
		if len(kv.Value) == 0 {
			continue
		}
		if kv.Key == jdh.KeyId {
			id = kv.Value[0]
			break
		}
	}
	if len(id) == 0 {
		return errors.New("specimen without identification")
	}
	sp, ok := s.ids[id]
	if !ok {
		return nil
	}
	spe := sp.data
	for _, kv := range vals {
		switch kv.Key {
		case jdh.SpeBasis:
			v := jdh.UnknownBasis
			if len(kv.Value) > 0 {
				v = jdh.GetBasisOfRecord(strings.TrimSpace(kv.Value[0]))
			}
			if spe.Basis == v {
				continue
			}
			spe.Basis = v
		case jdh.SpeCatalog:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.TrimSpace(kv.Value[0])
			}
			if spe.Catalog == v {
				continue
			}
			if len(v) > 0 {
				if _, ok := s.ids[v]; ok {
					return fmt.Errorf("specimen catalog code %s already in use", kv.Value)
				}
			}
			if len(spe.Catalog) > 0 {
				delete(s.ids, spe.Catalog)
			}
			spe.Catalog = v
			if len(v) > 0 {
				s.ids[v] = sp
			}
		case jdh.SpeCollector:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.Join(strings.Fields(kv.Value[0]), " ")
			}
			if spe.Collector == v {
				continue
			}
			spe.Collector = v
		case jdh.SpeDataset:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.TrimSpace(kv.Value[0])
			}
			if spe.Dataset == v {
				continue
			}
			if len(v) > 0 {
				if !s.db.d.isInDB(v) {
					continue
				}
			}
			spe.Dataset = v
		case jdh.SpeDate:
			if len(kv.Value) > 0 {
				v := strings.TrimSpace(kv.Value[0])
				t, err := time.Parse(jdh.Iso8601, v)
				if err != nil {
					return err
				}
				if spe.Date.Equal(t) {
					continue
				}
				spe.Date = t
				break
			}
			if spe.Date.IsZero() {
				continue
			}
			spe.Date = time.Time{}
		case jdh.SpeDeterminer:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.Join(strings.Fields(kv.Value[0]), " ")
			}
			if spe.Determiner == v {
				continue
			}
			spe.Determiner = v
		case jdh.SpeLocality:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.Join(strings.Fields(kv.Value[0]), " ")
			}
			if spe.Locality == v {
				continue
			}
			spe.Locality = v
		case jdh.SpeTaxon:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.TrimSpace(kv.Value[0])
			}
			if len(v) == 0 {
				continue
			}
			if spe.Taxon == v {
				continue
			}
			tax, ok := s.taxId[v]
			if !ok {
				if !s.db.t.isInDB(v) {
					continue
				}
				tax = &speTaxon{
					id:    v,
					specs: list.New(),
				}
				tax.elem = s.taxLs.PushBack(tax)
				s.taxId[tax.id] = tax
			}
			oldtax := sp.taxon
			oldtax.specs.Remove(sp.elem)
			sp.elem = tax.specs.PushBack(sp)
			sp.taxon = tax
			sp.data.Taxon = tax.id
			if oldtax.specs.Len() == 0 {
				oldtax.specs = nil
				s.taxLs.Remove(oldtax.elem)
				oldtax.elem = nil
				delete(s.taxId, oldtax.id)
			}
		case jdh.GeoCountry:
			v := geography.Country("")
			if len(kv.Value) > 0 {
				v = geography.GetCountry(strings.Join(strings.Fields(kv.Value[0]), " "))
			}
			if spe.Geography.Country == v {
				continue
			}
			spe.Geography.Country = v
		case jdh.GeoCounty:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.Join(strings.Fields(kv.Value[0]), " ")
			}
			if spe.Geography.County == v {
				continue
			}
			spe.Geography.County = v
		case jdh.GeoLonLat:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.TrimSpace(kv.Value[0])
			}
			if len(v) == 0 {
				if !spe.Georef.IsValid() {
					continue
				}
				spe.Georef = geography.InvalidGeoref()
				break
			}
			coor := strings.Split(v, ",")
			if len(coor) != 2 {
				return errors.New("invalid geographic coordinate values")
			}
			lon, err := strconv.ParseFloat(coor[0], 64)
			if err != nil {
				return err
			}
			lat, err := strconv.ParseFloat(coor[1], 64)
			if err != nil {
				return err
			}
			if (lon == 0) || (lon == 1) || (lat == 0) || (lat == 1) {
				return errors.New("invalid geographic coordinate values")
			}
			if (!geography.IsLon(lon)) || (!geography.IsLat(lat)) {
				return errors.New("invalid geographic coordinate values")
			}
			spe.Georef.Point = geography.Point{Lon: lon, Lat: lat}
		case jdh.GeoSource:
			if !spe.Georef.IsValid() {
				continue
			}
			v := ""
			if len(kv.Value) > 0 {
				v = strings.Join(strings.Fields(kv.Value[0]), " ")
			}
			if spe.Georef.Source == v {
				continue
			}
			spe.Georef.Source = v
		case jdh.GeoState:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.Join(strings.Fields(kv.Value[0]), " ")
			}
			if spe.Geography.State == v {
				continue
			}
			spe.Geography.State = v
		case jdh.GeoUncertainty:
			if !spe.Georef.IsValid() {
				continue
			}
			v := ""
			if len(kv.Value) > 0 {
				v = strings.TrimSpace(kv.Value[0])
			}
			un64, err := strconv.ParseUint(v, 10, 0)
			if err != nil {
				return err
			}
			un := uint(un64)
			if un == spe.Georef.Uncertainty {
				continue
			}
			spe.Georef.Uncertainty = un
		case jdh.GeoValidation:
			if !spe.Georef.IsValid() {
				continue
			}
			v := ""
			if len(kv.Value) > 0 {
				v = strings.Join(strings.Fields(kv.Value[0]), " ")
			}
			if spe.Georef.Validation == v {
				continue
			}
			spe.Georef.Validation = v
		case jdh.KeyComment:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.TrimSpace(kv.Value[0])
			}
			if spe.Comment == v {
				continue
			}
			spe.Comment = v
		case jdh.KeyExtern:
			ok := false
			for _, v := range kv.Value {
				v = strings.TrimSpace(v)
				if len(v) == 0 {
					continue
				}
				serv, ext, err := jdh.ParseExtern(v)
				if err != nil {
					return err
				}
				if len(ext) == 0 {
					if !s.delExtern(sp, serv) {
						continue
					}
					ok = true
					continue
				}
				if s.addExtern(sp, v) != nil {
					continue
				}
				ok = true
			}
			if !ok {
				continue
			}
		case jdh.KeyReference:
			v := ""
			if len(kv.Value) > 0 {
				v = strings.TrimSpace(kv.Value[0])
			}
			if spe.Reference == v {
				continue
			}
			spe.Reference = v
		default:
			continue
		}
		s.changed = true
	}
	return nil
}
Example #3
0
func (db *DB) occurrences(kvs []jdh.KeyValue) (jdh.ListScanner, error) {
	l := &listScanner{
		c:   make(chan interface{}, 20),
		end: make(chan struct{}),
	}
	id := ""
	var tax int64
	for _, kv := range kvs {
		if len(kv.Value) == 0 {
			continue
		}
		if kv.Key == jdh.SpeTaxon {
			id = strings.TrimSpace(kv.Value[0])
			var err error
			tax, err = strconv.ParseInt(id, 10, 64)
			if err != nil {
				return nil, err
			}
			break
		}
		if kv.Key == jdh.SpeTaxonParent {
			id = strings.TrimSpace(kv.Value[0])
			break
		}
	}
	if len(id) == 0 {
		return nil, errors.New("taxon " + id + " without [ny] identification")
	}
	go func() {
		vals := url.Values{}
		vals.Add("taxonKey", id)
		vals.Add("basisOfRecord", "PRESERVED_SPECIMEN")
		vals.Add("basisOfRecord", "FOSSIL_SPECIMEN")
		for _, kv := range kvs {
			if len(kv.Value) == 0 {
				continue
			}
			switch kv.Key {
			case jdh.GeoCountry:
				for _, v := range kv.Value {
					vals.Add("country", string(geography.GetCountry(v)))
				}
			case jdh.SpeGeoref:
				if kv.Value[0] == "true" {
					vals.Set("has_coordinate", "true")
				} else if kv.Value[0] == "false" {
					vals.Set("has_coordinate", "false")
				}
			}
		}
		for off := int64(0); ; {
			if off > 0 {
				vals.Set("offset", strconv.FormatInt(off, 10))
			}
			request := wsHead + "occurrence/search?" + vals.Encode()
			an := new(occAnswer)
			if err := db.listRequest(request, an); err != nil {
				l.setErr(err)
				return
			}
			for _, oc := range an.Results {
				if tax > 0 {
					if oc.TaxonKey != tax {
						continue
					}
				}
				select {
				case l.c <- oc.copy():
				case <-l.end:
					return
				}
			}
			if an.EndOfRecords {
				break
			}
			off += an.Limit
		}
		select {
		case l.c <- nil:
		case <-l.end:
		}
	}()
	return l, nil
}
Example #4
0
// List returns a list of specimens.
func (s *specimens) list(vals []jdh.KeyValue) (*list.List, error) {
	l := list.New()
	noVal := true
	// creates the list
	for _, kv := range vals {
		if len(kv.Value) == 0 {
			continue
		}
		if kv.Key == jdh.SpeTaxon {
			if len(kv.Value[0]) == 0 {
				return nil, errors.New("taxon without identification")
			}
			tax, ok := s.taxId[kv.Value[0]]
			if !ok {
				return l, nil
			}
			for e := tax.specs.Front(); e != nil; e = e.Next() {
				sp := e.Value.(*specimen)
				l.PushBack(sp.data)
			}
			noVal = false
			break
		}
		if kv.Key == jdh.SpeTaxonParent {
			if len(kv.Value[0]) == 0 {
				return nil, errors.New("taxon without identification")
			}
			pId := kv.Value[0]
			if !s.db.t.isInDB(pId) {
				return l, nil
			}
			for m := s.taxLs.Front(); m != nil; m = m.Next() {
				tax := m.Value.(*speTaxon)
				if tax.id != pId {
					if !s.db.t.isDesc(tax.id, pId) {
						continue
					}
				}
				for e := tax.specs.Front(); e != nil; e = e.Next() {
					sp := e.Value.(*specimen)
					l.PushBack(sp.data)
				}
			}
			noVal = false
			break
		}
	}
	if noVal {
		return nil, errors.New("taxon without identification")
	}

	//filters the list.
	for _, kv := range vals {
		if l.Len() == 0 {
			break
		}
		if len(kv.Value) == 0 {
			continue
		}
		switch kv.Key {
		case jdh.GeoCountry:
			for e := l.Front(); e != nil; {
				nx := e.Next()
				spe := e.Value.(*jdh.Specimen)
				remove := true
				for _, v := range kv.Value {
					c := geography.GetCountry(v)
					if len(c) == 0 {
						continue
					}
					if spe.Geography.Country == c {
						remove = false
						break
					}
				}
				if remove {
					l.Remove(e)
				}
				e = nx
			}
		case jdh.SpeGeoref:
			if (kv.Value[0] != "true") && (kv.Value[0] != "false") {
				continue
			}
			ok := false
			if kv.Value[0] == "true" {
				ok = true
			}
			for e := l.Front(); e != nil; {
				nx := e.Next()
				spe := e.Value.(*jdh.Specimen)
				if spe.Georef.IsValid() != ok {
					l.Remove(e)
				}
				e = nx
			}
		}
	}
	return l, nil
}