Example #1
0
File: editor.go Project: kego/ke
func GetEmbedEditable(ctx context.Context, node *node.Node, embed *system.Reference) (editable.Editable, error) {

	if node == nil || node.Null || node.Missing {
		return nil, nil
	}

	if *node.Type.Id == *embed {
		return GetEditable(ctx, node), nil
	}

	jcache := jsonctx.FromContext(ctx)
	nf, df, ok := jcache.GetNewFunc(embed.Package, embed.Name)
	if !ok {
		return nil, kerr.New("DGWDERFPVV", "Can't find %s in jsonctx", embed.String())
	}
	t := reflect.TypeOf(nf())
	if df != nil {
		t = t.Elem()
	}

	v := node.Val
	for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
		v = v.Elem()
	}

	var field reflect.Value
	for i := 0; i < v.Type().NumField(); i++ {
		f := v.Type().Field(i)
		if f.Anonymous && f.Type == t {
			field = v.Field(i)
			break
		}
	}
	if field == (reflect.Value{}) {
		return nil, kerr.New("UDBOWYUBER", "Can't find %s field in struct", t)
	}

	// This is the recommended method of presenting an custom editor.
	if ed, ok := field.Interface().(editable.Editable); ok {
		return ed, nil
	}

	editors := clientctx.FromContext(ctx)

	// Don't do this. Implement the Editable interface instead. We can't do this
	// for system types so we use this method instead.
	if e, ok := editors.Get(embed.String()); ok {
		return e, nil
	}

	return nil, nil

}
Example #2
0
func NewStructFragmentView(ctx context.Context, node *node.Node, origin *system.Reference) *StructFragmentView {
	v := &StructFragmentView{}
	v.View = New(ctx, v)
	v.model = v.App.Editors.Get(node)
	v.origin = origin
	if ti, ok := sysctx.FromContext(ctx).GetType(origin.Package, origin.Name); ok {
		v.originType = ti.(*system.Type)
	} else {
		v.App.Fail <- kerr.New("DNMXCJXNVU", "Type %s not found in system context", origin.String())
		return nil
	}
	return v
}
Example #3
0
File: node.go Project: kego/ke
func extractType(ctx context.Context, in system.Packed, rule *system.RuleWrapper) (*system.Type, error) {

	parentInterface := rule != nil && rule.Parent != nil && rule.Parent.Interface
	ruleInterface := rule != nil && rule.Struct != nil && rule.Struct.Interface

	if parentInterface && ruleInterface {
		return nil, kerr.New("TDXTPGVFAK", "Can't have interface type and interface rule at the same time")
	}

	if rule != nil && rule.Parent != nil && !parentInterface && !ruleInterface {
		// If we have a rule with the parent, and it's not an interface, then
		// we just return the parent type of the rule.
		return rule.Parent, nil
	}

	// if the rule is nil (e.g. unpacking into an unknown type) or the type is
	// an interface, we ensure the input is a map
	if rule == nil || parentInterface {
		if in == nil {
			return nil, nil
		}
		switch in.Type() {
		case system.J_NULL:
			// item is nil, so we don't know the concrete type yet.
			return nil, nil
		case system.J_MAP:
			break
		default:
			return nil, kerr.New("DLSQRFLINL", "Input %s should be J_MAP if rule is nil or an interface type", in.Type())
		}
	}

	// if the rule is an interface rule, we ensure the input is a map or a native value
	if ruleInterface {
		if in == nil {
			return nil, nil
		}
		switch in.Type() {
		case system.J_NULL:
			// item is nil, so we don't know the concrete type yet.
			return nil, nil
		case system.J_MAP:
			break
		case system.J_STRING, system.J_NUMBER, system.J_BOOL:
			// if the input value is a native value, we will be unpacking into
			// the parent type of the rule
			return rule.Parent, nil
		default:
			return nil, kerr.New("SNYLGBJYTM", "Input %s should be J_MAP, J_STRING, J_NUMBER or J_BOOL if rule is interface rule", in.Type())
		}
	}

	ob := in.Map()
	typeField, ok := ob["type"]
	if !ok {
		return nil, kerr.New("HBJVDKAKBJ", "Input must have type field if rule is nil or an interface type")
	}
	var r system.Reference
	if err := r.Unpack(ctx, typeField, false); err != nil {
		return nil, kerr.Wrap("YXHGIBXCOC", err)
	}
	t, ok := r.GetType(ctx)
	if !ok {
		return nil, kerr.New("IJFMJJWVCA", "Could not find type %s", r.Value())
	}
	return t, nil
}