-
Notifications
You must be signed in to change notification settings - Fork 215
/
PolicyImporter.java
90 lines (82 loc) · 3.97 KB
/
PolicyImporter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
* Copyright (c) 2022 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.policies.model;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Policy model functionality used in order to perform the importing/merging of imported {@link PolicyEntry}s into the
* importing Policy.
*
* @since 3.x.0 TODO ditto#298
*/
public final class PolicyImporter {
private PolicyImporter() {
throw new AssertionError();
}
/**
* Merges potentially {@code imported} {@link PolicyEntry}s from the passed {@code policy} into the policy entries
* of this passed policy returning a new Set with the combined/merged policy entries.
*
* @param policy the Policy to use all contained {@link PolicyEntry}s from, importing configured
* {@link PolicyImports} by using the provided {@code policyLoader} used to resolve/load the imported policies.
* @param policyLoader a function to load imported policies, e.g. provided by a cache.
* @return a combined set of existing {@link PolicyEntry}s from the passed {@code policy} merged with policy entries
* from imported policies.
*/
public static Set<PolicyEntry> mergeImportedPolicyEntries(final Policy policy,
final Function<PolicyId, Optional<Policy>> policyLoader) {
return policy.getPolicyImports().stream()
.map(policyImport -> {
final PolicyId importedPolicyId = policyImport.getImportedPolicyId();
final Optional<Policy> loadedPolicyOpt = policyLoader.apply(importedPolicyId);
return loadedPolicyOpt.map(loadedPolicy -> {
final ImportedLabels importedLabels = policyImport.getEffectedImports()
.map(EffectedImports::getImportedLabels)
.orElse(ImportedLabels.none());
return rewriteImportedLabels(importedPolicyId, loadedPolicy, importedLabels);
}).orElse(Collections.emptySet());
})
.reduce(policy.getEntriesSet(), PolicyImporter::combineSets, PolicyImporter::combineSets);
}
private static Set<PolicyEntry> rewriteImportedLabels(final PolicyId importedPolicyId, final Policy importedPolicy,
final Collection<Label> importedLabels) {
return importedPolicy.getEntriesSet().stream()
.flatMap(importedEntry -> importEntry(importedLabels, importedEntry))
.map(entry -> PoliciesModelFactory.newPolicyEntry(
PoliciesModelFactory.newImportedLabel(importedPolicyId, entry.getLabel()),
entry.getSubjects(),
entry.getResources(),
entry.getImportableType()
))
.collect(Collectors.toSet());
}
private static Stream<PolicyEntry> importEntry(final Collection<Label> importedLabels, final PolicyEntry importedEntry) {
switch (importedEntry.getImportableType()) {
case IMPLICIT:
return Stream.of(importedEntry);
case EXPLICIT:
return importedLabels.contains(importedEntry.getLabel()) ? Stream.of(importedEntry) : Stream.empty();
case NEVER:
default:
return Stream.empty();
}
}
private static Set<PolicyEntry> combineSets(final Set<PolicyEntry> set1, final Set<PolicyEntry> set2) {
return Stream.concat(set1.stream(), set2.stream()).collect(Collectors.toSet());
}
}