Exemple #1
0
func TestParser(t *testing.T) {
	testLogger := logger.NewTestLogger(t)

	for _, fixture := range []struct {
		String      string
		Length      int
		Definitions []*tag.Definition
	}{
		{`field:foo;complex_field(name:param,name2:param2,name_3:3);field:1;last_field`,
			4,
			[]*tag.Definition{
				{Name: "field", Value: "foo"},
				{Name: "complex_field", Parameters: []tag.Parameter{{Key: "name", Value: "param"}, {Key: "name2", Value: "param2"}, {Key: "name_3", Value: "3"}}},
				{Name: "field", Value: "1"},
				{Name: "last_field"},
			},
		},
	} {
		parser := tag.NewParser(strings.NewReader(fixture.String))
		parser.SetLogger(testLogger)
		definitions, err := parser.Parse()
		test.Fatal(t, err, nil)
		test.Fatal(t, len(definitions), fixture.Length)
		test.Fatal(t, reflect.DeepEqual(definitions, fixture.Definitions), true)
	}

}
Exemple #2
0
func ExampleParser() {
	// Let's parse the meta tag in Title field of type Book
	type Book struct {
		Title string `meta:"isbn:11010303030;published;author(firstname:john,lastname:doe);editor:apress"`
	}
	// let's get the tag
	titleField, _ := reflect.TypeOf(Book{}).FieldByName("Title")
	metaTag := titleField.Tag.Get("meta")
	// let's create a parser
	parser := tag.NewParser(strings.NewReader(metaTag))
	// do parse
	definitions, err := parser.Parse()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(definitions)
	// Output:
	// [[ Name 'isbn' , Value '11010303030' , Params '[]' ] [ Name 'published' , Value '' , Params '[]' ] [ Name 'author' , Value '' , Params '[{Key:firstname Value:john} {Key:lastname Value:doe}]' ] [ Name 'editor' , Value 'apress' , Params '[]' ]]
}
Exemple #3
0
// getTypeMetadatas takes a pointer to struct and returns the metadata
// for the struct or an error if the struct tag is invalid.
func getTypeMetadatas(value interface{}) (meta metadata, err error) {
	Value := reflect.Indirect(reflect.ValueOf(value))
	Type := Value.Type()
	// for each field in struct, read its struct tag and
	// create a metadata for the field if needed
	for i := 0; i < Value.NumField(); i++ {
		Field := Type.Field(i)
		MetaField := field{name: Field.Name, key: strings.ToLower(Field.Name)}
		// check bson struct tag and extract the document key
		Tag := Field.Tag.Get("bson")
		parts := strings.Split(Tag, ",")
		if len(parts) > 0 {
			if key := strings.TrimSpace(parts[0]); key != "" {
				MetaField.key = key
				if key == "_id" {
					meta.idField = Field.Name
					meta.idKey = "_id"
				}
				// ignore the field and continue
				if key == "-" {
					MetaField.ignore = true
					continue
				}
			}
		}
		if len(parts) > 1 {
			if part := strings.TrimSpace(parts[1]); part == "omitempty" {
				MetaField.omitempty = true
			}
		}
		Tag = Field.Tag.Get("odm")
		if Tag == "-" {
			MetaField.ignore = true
			continue
		}
		parser := tag.NewParser(strings.NewReader(Tag))
		var definitions []*tag.Definition
		definitions, err = parser.Parse()
		if err != nil {
			return meta, err
		}
		for _, definition := range definitions {
			switch strings.ToLower(definition.Name) {

			case "id":
				meta.idField = Field.Name
			case "omitempty":
				MetaField.omitempty = true
			case "index":
				MetaField.index = true
				for _, parameter := range definition.Parameters {
					switch toLower(parameter.Key) {
					case "unique":
						MetaField.unique = true
					}
				}
			case "referencemany", "referenceone":
				Relation := relation{}
				switch strings.ToLower(definition.Name) {
				case "referencemany":
					Relation.relation = referenceMany
					MetaField.key = "odm:" + strings.ToLower(Field.Name) + "ids"
				case "referenceone":
					Relation.relation = referenceOne
					MetaField.key = "odm:" + strings.ToLower(Field.Name) + "id"
				}
				for _, parameter := range definition.Parameters {
					switch strings.ToLower(parameter.Key) {
					case "mappedby":
						Relation.mapped = mappedBy
						Relation.mappedField = parameter.Value
					case "inversedby":
						Relation.mapped = inversedBy
						Relation.mappedField = parameter.Value
					case "targetdocument":
						Relation.targetDocument = parameter.Value
					case "cascade":
						switch strings.ToLower(parameter.Value) {
						case "persist":
							Relation.cascade = persist
						case "remove":
							Relation.cascade = remove
						case "all":
							Relation.cascade = all
						}
					case "storeid":
						Relation.idStorageField = parameter.Value
					case "load":
						switch strings.ToLower(parameter.Value) {
						case "eager":
							Relation.load = eager

						}
					default:
						return meta, ErrInvalidAnnotation
					}
					MetaField.relation = Relation
				}
			default:
				return meta, ErrInvalidAnnotation
			}
		}
		// remove index definition if field has a relation
		if MetaField.index == true && MetaField.hasRelation() {
			MetaField.index = false
		}
		// use a specific field to store related ids
		if MetaField.relation.idStorageField != "" {

			if key := resolveKeyForField(Type, MetaField.relation.idStorageField); key != "" {

				MetaField.key = key
			}
		}
		meta.fields = append(meta.fields, MetaField)
	}
	return
}