blob: b5c8cec04d8cbbbfb39c91cbb656fd827d5fbe75 [file] [log] [blame]
Bob Badoura99ac622021-10-25 16:21:00 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package compliance
16
17import (
18 "fmt"
19 "strings"
20)
21
22// LicenseCondition describes an individual license condition or requirement
23// originating at a specific target node. (immutable)
24//
25// e.g. A module licensed under GPL terms would originate a `restricted` condition.
26type LicenseCondition struct {
27 name string
28 origin *TargetNode
29}
30
31// Name returns the name of the condition. e.g. "restricted" or "notice"
32func (lc LicenseCondition) Name() string {
33 return lc.name
34}
35
36// Origin identifies the TargetNode where the condition originates.
37func (lc LicenseCondition) Origin() *TargetNode {
38 return lc.origin
39}
40
41// asString returns a string representation of a license condition:
42// origin+separator+condition.
43func (lc LicenseCondition) asString(separator string) string {
44 return lc.origin.name + separator + lc.name
45}
46
47// ConditionList implements introspection methods to arrays of LicenseCondition.
48type ConditionList []LicenseCondition
49
50
51// ConditionList orders arrays of LicenseCondition by Origin and Name.
52
53// Len returns the length of the list.
54func (l ConditionList) Len() int { return len(l) }
55
56// Swap rearranges 2 elements in the list so each occupies the other's former position.
57func (l ConditionList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
58
59// Less returns true when the `i`th element is lexicographically less than tht `j`th element.
60func (l ConditionList) Less(i, j int) bool {
61 if l[i].origin.name == l[j].origin.name {
62 return l[i].name < l[j].name
63 }
64 return l[i].origin.name < l[j].origin.name
65}
66
67// String returns a string representation of the set.
68func (cl ConditionList) String() string {
69 var sb strings.Builder
70 fmt.Fprintf(&sb, "[")
71 sep := ""
72 for _, lc := range cl {
73 fmt.Fprintf(&sb, "%s%s:%s", sep, lc.origin.name, lc.name)
74 sep = ", "
75 }
76 fmt.Fprintf(&sb, "]")
77 return sb.String()
78}
79
Bob Badourfa739da2021-10-25 16:21:00 -070080// Names returns the list of the conditions' names.
81func (cl ConditionList) Names() []string {
82 result := make([]string, 0, len(cl))
83 for _, lc := range cl {
84 result = append(result, lc.name)
85 }
86 return result
87}
88
Bob Badoura99ac622021-10-25 16:21:00 -070089// HasByName returns true if the list contains any condition matching `name`.
90func (cl ConditionList) HasByName(name ConditionNames) bool {
91 for _, lc := range cl {
92 if name.Contains(lc.name) {
93 return true
94 }
95 }
96 return false
97}
98
99// ByName returns the sublist of conditions that match `name`.
100func (cl ConditionList) ByName(name ConditionNames) ConditionList {
101 result := make(ConditionList, 0, cl.CountByName(name))
102 for _, lc := range cl {
103 if name.Contains(lc.name) {
104 result = append(result, lc)
105 }
106 }
107 return result
108}
109
110// CountByName returns the size of the sublist of conditions that match `name`.
111func (cl ConditionList) CountByName(name ConditionNames) int {
112 size := 0
113 for _, lc := range cl {
114 if name.Contains(lc.name) {
115 size++
116 }
117 }
118 return size
119}
120
121// HasByOrigin returns true if the list contains any condition originating at `origin`.
122func (cl ConditionList) HasByOrigin(origin *TargetNode) bool {
123 for _, lc := range cl {
124 if lc.origin.name == origin.name {
125 return true
126 }
127 }
128 return false
129}
130
131// ByOrigin returns the sublist of conditions that originate at `origin`.
132func (cl ConditionList) ByOrigin(origin *TargetNode) ConditionList {
133 result := make(ConditionList, 0, cl.CountByOrigin(origin))
134 for _, lc := range cl {
135 if lc.origin.name == origin.name {
136 result = append(result, lc)
137 }
138 }
139 return result
140}
141
142// CountByOrigin returns the size of the sublist of conditions that originate at `origin`.
143func (cl ConditionList) CountByOrigin(origin *TargetNode) int {
144 size := 0
145 for _, lc := range cl {
146 if lc.origin.name == origin.name {
147 size++
148 }
149 }
150 return size
151}
152
153// ConditionNames implements the Contains predicate for slices of condition
154// name strings.
155type ConditionNames []string
156
157// Contains returns true if the name matches one of the ConditionNames.
158func (cn ConditionNames) Contains(name string) bool {
159 for _, cname := range cn {
160 if cname == name {
161 return true
162 }
163 }
164 return false
165}