func getTypeFromValueXFieldName(valueField string) string {
	fhirType := strings.TrimPrefix(valueField, "Value")
	switch fhirType {
	case "Instant", "Time", "Date", "DateTime", "Decimal", "Boolean", "Integer", "String", "Uri", "Base64Binary",
		"UnsignedInt", "PositiveInt", "Code", "Id", "Markdown", "Oid":
		fhirType = fmt.Sprintf("%s%s", strings.ToLower(fhirType[:1]), fhirType[1:])
	}
	return fhirType
}
getTypeFromValueXFieldName takes in a FHIR type with an uppercase letter and fixes it so it is lowercase if
it is a FHIR "primitive". This function has little to no value outside of the intended use case -- which is
to create the right type based on the field names for extension Value[x] properties.
package models
import (
	"errors"
	"fmt"
	"reflect"
	"strings"
	"gopkg.in/mgo.v2/bson"
)
func (e Extension) GetBSON() (interface{}, error) {
	value := reflect.ValueOf(e)
	for i := 0; i < value.NumField(); i++ {
		field := value.Field(i)
		fieldName := value.Type().Field(i).Name
		if !strings.HasPrefix(fieldName, "Value") {
			continue
		}
		var val interface{}
		switch field.Kind() {
		case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface:
			if !field.IsNil() {
				val = field.Elem().Interface()
				break
			}
		default:
			if field.CanInterface() && !reflect.DeepEqual(field.Interface(), reflect.Zero(field.Type()).Interface()) {
				val = field.Interface()
				break
			}
		}
		if val != nil {
			return bsonExtension(e.Url, getTypeFromValueXFieldName(fieldName), val)
		}
	}
	return bsonExtension(e.Url, "string", "")
}
func bsonExtension(url string, fhirType string, value interface{}) (extension bson.M, err error) {
	var i int
	if i = strings.LastIndex(url, "/"); i < 0 || i == (len(url)-1) {
		err = fmt.Errorf("Couldn't determine extension name for %s", url)
		return
	}
	name := url[i+1:]
	extension = bson.M{
		"@context": bson.M{
			name: contextDefinition{
				ID:   url,
				Type: fhirType,
			},
		},
		name: value,
	}
	return
}
func (e *Extension) SetBSON(raw bson.Raw) error {
	var rd bson.RawD
	err := raw.Unmarshal(&rd)
	if err != nil {
		return err
	}
	if len(rd) != 2 {
		return errors.New("Couldn't properly unmarshal extension; unrecognized format in BSON")
	}
	var context map[string]contextDefinition
	var dataElement bson.RawDocElem
	for i := range rd {
		switch rd[i].Name {
		case "@context":
			rd[i].Value.Unmarshal(&context)
		default:
			dataElement = rd[i]
		}
	}
	if _, ok := context[dataElement.Name]; !ok {
		return fmt.Errorf("Couldn't properly unmarshal extension; key %s not found in @context", dataElement.Name)
	}
	fhirType := context[dataElement.Name].Type
	fieldName := fmt.Sprintf("Value%s%s", strings.ToUpper(fhirType[:1]), fhirType[1:])
	field := reflect.ValueOf(e).Elem().FieldByName(fieldName)
	if !field.IsValid() {
		return fmt.Errorf("Couldn't find extension field %s", fieldName)
	} else if !field.CanSet() {
		return fmt.Errorf("Couldn't set a value for field %s", fieldName)
	}
	val := reflect.New(field.Type())
	if err := dataElement.Value.Unmarshal(val.Interface()); err != nil {
		return err
	}
	field.Set(val.Elem())
	e.Url = context[dataElement.Name].ID
	return nil
}
type contextDefinition struct {
	ID   string `bson:"@id,omitempty"`
	Type string `bson:"@type,omitempty"`
}