-
Notifications
You must be signed in to change notification settings - Fork 188
/
ValueMetadataComputation.java
145 lines (127 loc) · 6.92 KB
/
ValueMetadataComputation.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* Copyright (c) 2020 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/
package com.evolveum.midpoint.model.common.mapping;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.repo.common.expression.Source;
import com.evolveum.midpoint.schema.metadata.MidpointValueMetadataFactory;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.xml.ns._public.common.common_3.MetadataMappingType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ValueMetadataType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.VariableBindingDefinitionType;
import org.jetbrains.annotations.NotNull;
import javax.xml.namespace.QName;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
/**
* Computation of value metadata for given combination of input values.
*
* Preliminary implementation.
* For example, it does no real consolidation: it simply adds all values into respective items.
*/
class ValueMetadataComputation {
@NotNull private final List<PrismValue> valuesTuple;
@NotNull private final SimpleValueMetadataComputer computer;
@NotNull private final OperationResult result;
@NotNull private final PrismContext prismContext;
@NotNull private final PrismContainerValue<ValueMetadataType> outputMetadata;
@NotNull private final PrismContainerDefinition<ValueMetadataType> metadataDefinition;
ValueMetadataComputation(@NotNull List<PrismValue> valuesTuple, SimpleValueMetadataComputer computer, @NotNull OperationResult result) {
this.valuesTuple = valuesTuple;
this.computer = computer;
this.result = result;
this.prismContext = computer.metadataMappingEvaluator.prismContext;
//noinspection unchecked
this.outputMetadata = new ValueMetadataType(prismContext).asPrismContainerValue();
this.metadataDefinition = Objects.requireNonNull(
prismContext.getSchemaRegistry().findContainerDefinitionByCompileTimeClass(ValueMetadataType.class),
"No definition of value metadata container");
}
public ValueMetadata execute() throws CommunicationException, ObjectNotFoundException, SchemaException,
SecurityViolationException, ConfigurationException, ExpressionEvaluationException {
List<MetadataMappingType> mappingBeans = computer.dataMapping.getMetadataHandling().getMapping();
for (MetadataMappingType mappingBean : mappingBeans) {
processMapping(mappingBean);
}
return MidpointValueMetadataFactory.createFrom(outputMetadata);
}
private void processMapping(MetadataMappingType mappingBean) throws CommunicationException, ObjectNotFoundException,
SchemaException, SecurityViolationException, ConfigurationException, ExpressionEvaluationException {
MetadataMappingImpl<?, ?> mapping = createMetadataMapping(mappingBean);
mapping.evaluate(computer.dataMapping.getTask(), result);
appendValues(mapping.getOutputPath(), mapping.getOutputTriple());
}
private void appendValues(ItemPath outputPath, PrismValueDeltaSetTriple<?> outputTriple) throws SchemaException {
ItemDelta<?, ?> itemDelta = prismContext.deltaFor(ValueMetadataType.class)
.item(outputPath)
.add(outputTriple.getNonNegativeValues())
.asItemDelta();
itemDelta.applyTo(outputMetadata);
}
private MetadataMappingImpl<?, ?> createMetadataMapping(MetadataMappingType mappingBean) throws SchemaException {
MetadataMappingBuilder<?, ?> builder = computer.metadataMappingEvaluator.mappingFactory.createMappingBuilder(mappingBean,
"metadata mapping in " + computer.dataMapping.getMappingContextDescription());
createSources(builder, mappingBean);
builder.targetContext(metadataDefinition)
.now(computer.dataMapping.now)
.conditionMaskOld(false); // We are not interested in old values (deltas are irrelevant in metadata mappings).
return builder.build();
}
// TODO unify with parsing data mapping sources (MappingParser class)
private void createSources(MetadataMappingBuilder<?, ?> builder, MetadataMappingType mappingBean) throws SchemaException {
for (VariableBindingDefinitionType sourceDef : mappingBean.getSource()) {
ItemPath sourcePath = getSourcePath(sourceDef);
QName sourceName = getSourceName(sourceDef, sourcePath);
ItemDefinition sourceDefinition = getAdaptedSourceDefinition(sourcePath);
Item sourceItem = sourceDefinition.instantiate();
//noinspection unchecked
sourceItem.addAll(getSourceValues(sourcePath));
//noinspection unchecked
Source<?, ?> source = new Source<>(sourceItem, null, null, sourceName, sourceDefinition);
source.recompute();
builder.additionalSource(source);
}
}
@NotNull
private MutableItemDefinition getAdaptedSourceDefinition(ItemPath sourcePath) {
ItemDefinition sourceDefinition =
Objects.requireNonNull(metadataDefinition.findItemDefinition(sourcePath),
() -> "No definition for '" + sourcePath + "' in " + getContextDescription());
MutableItemDefinition sourceDefinitionMultivalued =
sourceDefinition.clone().toMutable();
sourceDefinitionMultivalued.setMaxOccurs(-1);
return sourceDefinitionMultivalued;
}
private Collection<?> getSourceValues(ItemPath sourcePath) throws SchemaException {
Collection<PrismValue> values = new HashSet<>();
for (PrismValue dataValue : valuesTuple) {
if (dataValue != null) {
Item<PrismValue, ItemDefinition> sourceItem = dataValue.getValueMetadata().findItem(sourcePath);
if (sourceItem != null) {
values.addAll(CloneUtil.cloneCollectionMembers(sourceItem.getValues()));
}
}
}
return values;
}
private QName getSourceName(VariableBindingDefinitionType sourceDef, ItemPath sourcePath) {
return sourceDef.getName() != null ? sourceDef.getName() : ItemPath.toName(sourcePath.last());
}
private ItemPath getSourcePath(VariableBindingDefinitionType sourceDef) {
return Objects.requireNonNull(sourceDef.getPath(), () -> "No source path in " + getContextDescription())
.getItemPath();
}
private String getContextDescription() {
return computer.getContextDescription(); // TODO indication of value tuple being processed
}
}