1package graph
2
3import (
4	"fmt"
5
6	"github.com/wallix/awless/cloud/properties"
7	"github.com/wallix/awless/cloud/rdf"
8	tstore "github.com/wallix/triplestore"
9)
10
11type Resolver interface {
12	Resolve(snap tstore.RDFGraph) ([]*Resource, error)
13}
14
15type ById struct {
16	Id string
17}
18
19func (r *ById) Resolve(snap tstore.RDFGraph) ([]*Resource, error) {
20	resolver := &ByProperty{Key: properties.ID, Value: r.Id}
21	return resolver.Resolve(snap)
22}
23
24type ByTypeAndProperty struct {
25	Type  string
26	Key   string
27	Value interface{}
28}
29
30func (r *ByTypeAndProperty) Resolve(snap tstore.RDFGraph) ([]*Resource, error) {
31	var resources []*Resource
32
33	if r.Value == nil {
34		return resources, nil
35	}
36	rdfpropLabel, ok := rdf.Labels[r.Key]
37	if !ok {
38		return resources, fmt.Errorf("resolve by property: undefined property label '%s'", r.Key)
39	}
40	rdfProp, err := rdf.Properties.Get(rdfpropLabel)
41	if err != nil {
42		return resources, fmt.Errorf("resolve by property: %s", err)
43	}
44	obj, err := marshalToRdfObject(r.Value, rdfProp.RdfsDefinedBy, rdfProp.RdfsDataType)
45	if err != nil {
46		return resources, fmt.Errorf("resolve by property: unmarshaling property '%s': %s", r.Key, err)
47	}
48	for _, t := range snap.WithPredObj(rdfpropLabel, obj) {
49		rt, err := resolveResourceType(snap, t.Subject())
50		if err != nil {
51			return resources, err
52		}
53		if rt == r.Type {
54			r := InitResource(rt, t.Subject())
55
56			if err := r.unmarshalFullRdf(snap); err != nil {
57				return resources, err
58			}
59			resources = append(resources, r)
60		}
61	}
62	return resources, nil
63}
64
65type ByProperty struct {
66	Key   string
67	Value interface{}
68}
69
70func (r *ByProperty) Resolve(snap tstore.RDFGraph) ([]*Resource, error) {
71	var resources []*Resource
72	if r.Value == nil {
73		return resources, nil
74	}
75	rdfpropLabel, ok := rdf.Labels[r.Key]
76	if !ok {
77		return resources, fmt.Errorf("resolve by property: undefined property label '%s'", r.Key)
78	}
79	rdfProp, err := rdf.Properties.Get(rdfpropLabel)
80	if err != nil {
81		return resources, fmt.Errorf("resolve by property: %s", err)
82	}
83	obj, err := marshalToRdfObject(r.Value, rdfProp.RdfsDefinedBy, rdfProp.RdfsDataType)
84	if err != nil {
85		return resources, fmt.Errorf("resolve by property: unmarshaling property '%s': %s", r.Key, err)
86	}
87	for _, t := range snap.WithPredObj(rdfpropLabel, obj) {
88		rt, err := resolveResourceType(snap, t.Subject())
89		if err != nil {
90			return resources, err
91		}
92		r := InitResource(rt, t.Subject())
93
94		if err := r.unmarshalFullRdf(snap); err != nil {
95			return resources, err
96		}
97		resources = append(resources, r)
98	}
99	return resources, nil
100}
101
102type And struct {
103	Resolvers []Resolver
104}
105
106func (r *And) Resolve(snap tstore.RDFGraph) (result []*Resource, err error) {
107	if len(r.Resolvers) == 0 {
108		return
109	}
110	result, err = r.Resolvers[0].Resolve(snap)
111	if err != nil {
112		return
113	}
114	gg := NewGraph()
115	if err = gg.AddResource(result...); err != nil {
116		return
117	}
118	for _, resolv := range r.Resolvers {
119		result, err = resolv.Resolve(gg.store.Snapshot())
120		if err != nil {
121			return
122		}
123		gg = NewGraph()
124		if err = gg.AddResource(result...); err != nil {
125			return
126		}
127	}
128	return
129}
130
131type Or struct {
132	Resolvers []Resolver
133}
134
135func (r *Or) Resolve(snap tstore.RDFGraph) (result []*Resource, err error) {
136	for _, resolv := range r.Resolvers {
137		result, err = resolv.Resolve(snap)
138		if err != nil {
139			return
140		}
141		if len(result) > 0 {
142			return
143		}
144	}
145	return
146}
147
148type ByType struct {
149	Typ string
150}
151
152func (r *ByType) Resolve(snap tstore.RDFGraph) ([]*Resource, error) {
153	var resources []*Resource
154	typ := namespacedResourceType(r.Typ)
155	for _, t := range snap.WithPredObj(rdf.RdfType, tstore.Resource(typ)) {
156		r := InitResource(r.Typ, t.Subject())
157		err := r.unmarshalFullRdf(snap)
158		if err != nil {
159			return resources, err
160		}
161		resources = append(resources, r)
162	}
163	return resources, nil
164}
165
166type ByTypes struct {
167	Typs []string
168}
169
170func (r *ByTypes) Resolve(snap tstore.RDFGraph) ([]*Resource, error) {
171	var res []*Resource
172	for _, t := range r.Typs {
173		bt := &ByType{t}
174		all, err := bt.Resolve(snap)
175		if err != nil {
176			return res, err
177		}
178		res = append(res, all...)
179	}
180
181	return res, nil
182}
183