Example #1
0
func hydrateProperties(v reflect.Value, component *token) error {

	vdref := dereferencePointerValue(v)
	vtype := vdref.Type()
	vkind := vdref.Kind()

	if vkind != reflect.Struct {
		return utils.NewError(hydrateProperties, "unable to hydrate properties of non-struct", v, nil)
	}

	n := vtype.NumField()
	for i := 0; i < n; i++ {

		prop := properties.PropertyFromStructField(vtype.Field(i))
		if prop == nil {
			continue // skip if field is ignored
		}

		vfield := vdref.Field(i)

		// first try to hydrate property values
		if properties, ok := component.properties[prop.Name]; ok {
			for _, prop := range properties {
				if err := hydrateProperty(vfield, prop); err != nil {
					msg := fmt.Sprintf("unable to hydrate property %s", prop.Name)
					return utils.NewError(hydrateProperties, msg, v, err)
				}
			}
		}

		// then try to hydrate components
		vtemp, _ := newValue(vfield)
		if tag, err := extractTagFromValue(vtemp); err != nil {
			msg := fmt.Sprintf("unable to extract tag from property %s", prop.Name)
			return utils.NewError(hydrateProperties, msg, v, err)
		} else if components, ok := component.components[tag]; ok {
			for _, comp := range components {
				if err := hydrateNestedComponent(vfield, comp); err != nil {
					msg := fmt.Sprintf("unable to hydrate component %s", prop.Name)
					return utils.NewError(hydrateProperties, msg, v, err)
				}
			}
		}
	}

	return nil

}
Example #2
0
func marshalStruct(v reflect.Value) (string, error) {

	var out []string

	// iterate over all fields
	vtype := v.Type()
	n := vtype.NumField()

	for i := 0; i < n; i++ {

		// keep a reference to the field value and definition
		fv := v.Field(i)
		fs := vtype.Field(i)

		// use the field definition to extract out property defaults
		p := properties.PropertyFromStructField(fs)
		if p == nil {
			continue // skip explicitly ignored fields and private members
		}

		fi := fv.Interface()

		// some fields are not properties, but actually nested objects.
		// detect those early using the property and object encoder...
		if _, ok := fi.(properties.CanEncodeValue); !ok && !isInvalidOrEmptyValue(fv) {
			if encoded, err := encode(fv, objectEncoder); err != nil {
				msg := fmt.Sprintf("unable to encode field %s", fs.Name)
				return "", utils.NewError(marshalStruct, msg, v.Interface(), err)
			} else if encoded != "" {
				// encoding worked! no need to process as a property
				out = append(out, encoded)
				continue
			}
		}

		// now check to see if the field value overrides the defaults...
		if !isInvalidOrEmptyValue(fv) {
			// first, check the field value interface for overrides...
			if overrides, err := properties.PropertyFromInterface(fi); err != nil {
				msg := fmt.Sprintf("field %s failed validation", fs.Name)
				return "", utils.NewError(marshalStruct, msg, v.Interface(), err)
			} else if p.Merge(overrides); p.Value == "" {
				// then, if we couldn't find an override from the interface,
				// try the simple string encoder...
				if p.Value, err = stringEncoder(fv); err != nil {
					msg := fmt.Sprintf("unable to encode field %s", fs.Name)
					return "", utils.NewError(marshalStruct, msg, v.Interface(), err)
				}
			}
		}

		// make sure we have a value by this point
		if !p.HasNameAndValue() {
			if p.OmitEmpty {
				continue
			} else if p.DefaultValue != "" {
				p.Value = p.DefaultValue
			} else if p.Required {
				msg := fmt.Sprintf("missing value for required field %s", fs.Name)
				return "", utils.NewError(Marshal, msg, v.Interface(), nil)
			}
		}

		// encode in the property
		out = append(out, properties.MarshalProperty(p))

	}

	// wrap the fields in the enclosing struct tags
	return tagAndJoinValue(v, out)

}