1// 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// LicenseConditionSet identifies sets of license conditions. 23type LicenseConditionSet LicenseCondition 24 25// AllLicenseConditions is the set of all recognized license conditions. 26const AllLicenseConditions = LicenseConditionSet(LicenseConditionMask) 27 28// NewLicenseConditionSet returns a set containing exactly the elements of 29// `conditions`. 30func NewLicenseConditionSet(conditions ...LicenseCondition) LicenseConditionSet { 31 cs := LicenseConditionSet(0x00) 32 for _, lc := range conditions { 33 cs |= LicenseConditionSet(lc) 34 } 35 return cs 36} 37 38// Plus returns a new set containing all of the elements of `cs` and all of the 39// `conditions`. 40func (cs LicenseConditionSet) Plus(conditions ...LicenseCondition) LicenseConditionSet { 41 result := cs 42 for _, lc := range conditions { 43 result |= LicenseConditionSet(lc) 44 } 45 return result 46} 47 48// Union returns a new set containing all of the elements of `cs` and all of the 49// elements of the `other` sets. 50func (cs LicenseConditionSet) Union(other ...LicenseConditionSet) LicenseConditionSet { 51 result := cs 52 for _, ls := range other { 53 result |= ls 54 } 55 return result 56} 57 58// MatchingAny returns the subset of `cs` equal to any of the `conditions`. 59func (cs LicenseConditionSet) MatchingAny(conditions ...LicenseCondition) LicenseConditionSet { 60 result := LicenseConditionSet(0x00) 61 for _, lc := range conditions { 62 result |= cs & LicenseConditionSet(lc) 63 } 64 return result 65} 66 67// MatchingAnySet returns the subset of `cs` that are members of any of the 68// `other` sets. 69func (cs LicenseConditionSet) MatchingAnySet(other ...LicenseConditionSet) LicenseConditionSet { 70 result := LicenseConditionSet(0x00) 71 for _, ls := range other { 72 result |= cs & ls 73 } 74 return result 75} 76 77// HasAny returns true when `cs` contains at least one of the `conditions`. 78func (cs LicenseConditionSet) HasAny(conditions ...LicenseCondition) bool { 79 for _, lc := range conditions { 80 if 0x0000 != (cs & LicenseConditionSet(lc)) { 81 return true 82 } 83 } 84 return false 85} 86 87// MatchesAnySet returns true when `cs` has a non-empty intersection with at 88// least one of the `other` condition sets. 89func (cs LicenseConditionSet) MatchesAnySet(other ...LicenseConditionSet) bool { 90 for _, ls := range other { 91 if 0x0000 != (cs & ls) { 92 return true 93 } 94 } 95 return false 96} 97 98// HasAll returns true when `cs` contains every one of the `conditions`. 99func (cs LicenseConditionSet) HasAll(conditions ...LicenseCondition) bool { 100 for _, lc := range conditions { 101 if 0x0000 == (cs & LicenseConditionSet(lc)) { 102 return false 103 } 104 } 105 return true 106} 107 108// MatchesEverySet returns true when `cs` has a non-empty intersection with 109// each of the `other` condition sets. 110func (cs LicenseConditionSet) MatchesEverySet(other ...LicenseConditionSet) bool { 111 for _, ls := range other { 112 if 0x0000 == (cs & ls) { 113 return false 114 } 115 } 116 return true 117} 118 119// Intersection returns the subset of `cs` that are members of every `other` 120// set. 121func (cs LicenseConditionSet) Intersection(other ...LicenseConditionSet) LicenseConditionSet { 122 result := cs 123 for _, ls := range other { 124 result &= ls 125 } 126 return result 127} 128 129// Minus returns the subset of `cs` that are not equaal to any `conditions`. 130func (cs LicenseConditionSet) Minus(conditions ...LicenseCondition) LicenseConditionSet { 131 result := cs 132 for _, lc := range conditions { 133 result &^= LicenseConditionSet(lc) 134 } 135 return result 136} 137 138// Difference returns the subset of `cs` that are not members of any `other` 139// set. 140func (cs LicenseConditionSet) Difference(other ...LicenseConditionSet) LicenseConditionSet { 141 result := cs 142 for _, ls := range other { 143 result &^= ls 144 } 145 return result 146} 147 148// Len returns the number of license conditions in the set. 149func (cs LicenseConditionSet) Len() int { 150 size := 0 151 for lc := LicenseConditionSet(0x01); 0x00 != (AllLicenseConditions & lc); lc <<= 1 { 152 if 0x00 != (cs & lc) { 153 size++ 154 } 155 } 156 return size 157} 158 159// AsList returns an array of the license conditions in the set. 160func (cs LicenseConditionSet) AsList() []LicenseCondition { 161 result := make([]LicenseCondition, 0, cs.Len()) 162 for lc := LicenseConditionSet(0x01); 0x00 != (AllLicenseConditions & lc); lc <<= 1 { 163 if 0x00 != (cs & lc) { 164 result = append(result, LicenseCondition(lc)) 165 } 166 } 167 return result 168} 169 170// Names returns an array of the names of the license conditions in the set. 171func (cs LicenseConditionSet) Names() []string { 172 result := make([]string, 0, cs.Len()) 173 for lc := LicenseConditionSet(0x01); 0x00 != (AllLicenseConditions & lc); lc <<= 1 { 174 if 0x00 != (cs & lc) { 175 result = append(result, LicenseCondition(lc).Name()) 176 } 177 } 178 return result 179} 180 181// IsEmpty returns true when the set contains no license conditions. 182func (cs LicenseConditionSet) IsEmpty() bool { 183 return 0x00 == (cs & AllLicenseConditions) 184} 185 186// String returns a human-readable string representation of the set. 187func (cs LicenseConditionSet) String() string { 188 return fmt.Sprintf("{%s}", strings.Join(cs.Names(), "|")) 189} 190