blob: dabdff5dcea4b2899b50090f6ec9d4b1e6e6930e [file] [log] [blame]
Bob Badour9ee7d032021-10-25 16:51:48 -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)
20
21// SourceSharePrivacyConflict describes an individual conflict between a source-sharing
22// condition and a source privacy condition
23type SourceSharePrivacyConflict struct {
24 SourceNode *TargetNode
25 ShareCondition LicenseCondition
26 PrivacyCondition LicenseCondition
27}
28
29// Error returns a string describing the conflict.
30func (conflict SourceSharePrivacyConflict) Error() string {
31 return fmt.Sprintf("%s %s from %s and must share from %s %s\n",
32 conflict.SourceNode.name,
33 conflict.PrivacyCondition.name, conflict.PrivacyCondition.origin.name,
34 conflict.ShareCondition.name, conflict.ShareCondition.origin.name)
35}
36
37// IsEqualTo returns true when `conflict` and `other` describe the same conflict.
38func (conflict SourceSharePrivacyConflict) IsEqualTo(other SourceSharePrivacyConflict) bool {
39 return conflict.SourceNode.name == other.SourceNode.name &&
40 conflict.ShareCondition.name == other.ShareCondition.name &&
41 conflict.ShareCondition.origin.name == other.ShareCondition.origin.name &&
42 conflict.PrivacyCondition.name == other.PrivacyCondition.name &&
43 conflict.PrivacyCondition.origin.name == other.PrivacyCondition.origin.name
44}
45
46// ConflictingSharedPrivateSource lists all of the targets where conflicting conditions to
47// share the source and to keep the source private apply to the target.
48func ConflictingSharedPrivateSource(lg *LicenseGraph) []SourceSharePrivacyConflict {
49 // shareSource is the set of all source-sharing resolutions.
50 shareSource := ResolveSourceSharing(lg)
51 if shareSource.IsEmpty() {
52 return []SourceSharePrivacyConflict{}
53 }
54
55 // privateSource is the set of all source privacy resolutions.
56 privateSource := ResolveSourcePrivacy(lg)
57 if privateSource.IsEmpty() {
58 return []SourceSharePrivacyConflict{}
59 }
60
61 // combined is the combination of source-sharing and source privacy.
62 combined := JoinResolutionSets(shareSource, privateSource)
63
64 // size is the size of the result
65 size := 0
66 for _, actsOn := range combined.ActsOn() {
67 rl := combined.ResolutionsByActsOn(actsOn)
68 size += rl.CountConditionsByName(ImpliesShared) * rl.CountConditionsByName(ImpliesPrivate)
69 }
70 if size == 0 {
71 return []SourceSharePrivacyConflict{}
72 }
73 result := make([]SourceSharePrivacyConflict, 0, size)
74 for _, actsOn := range combined.ActsOn() {
75 rl := combined.ResolutionsByActsOn(actsOn)
76 if len(rl) == 0 {
77 continue
78 }
79
80 pconditions := rl.ByName(ImpliesPrivate).AllConditions().AsList()
81 ssconditions := rl.ByName(ImpliesShared).AllConditions().AsList()
82
83 // report all conflicting condition combinations
84 for _, p := range pconditions {
85 for _, ss := range ssconditions {
86 result = append(result, SourceSharePrivacyConflict{actsOn, ss, p})
87 }
88 }
89 }
90 return result
91}