/*
* Copyright (c) 2010-2015 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.repo.sql.helpers;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author lazyman, katkav, mederly
*/
@Component
public class NameResolutionHelper {
private static final int MAX_OIDS_TO_RESOLVE_AT_ONCE = 200;
// TODO keep names between invocations (e.g. when called from searchObjects/searchContainers)
public void resolveNamesIfRequested(Session session, PrismContainerValue<?> containerValue, Collection<SelectorOptions<GetOperationOptions>> options) {
resolveNamesIfRequested(session, Collections.singletonList(containerValue), options);
}
public void resolveNamesIfRequested(Session session, List<? extends PrismContainerValue> containerValues, Collection<SelectorOptions<GetOperationOptions>> options) {
GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options);
if (!GetOperationOptions.isResolveNames(rootOptions)) {
return;
}
final Set<String> oidsToResolve = new HashSet<>();
Visitor oidExtractor = visitable -> {
if (visitable instanceof PrismReferenceValue) {
PrismReferenceValue value = (PrismReferenceValue) visitable;
if (value.getTargetName() != null) { // just for sure
return;
}
if (value.getObject() != null) { // improbable but possible
value.setTargetName(value.getObject().getName());
return;
}
if (value.getOid() == null) { // shouldn't occur as well
return;
}
oidsToResolve.add(value.getOid());
}
};
Set<PrismContainerValue> roots = containerValues.stream().map(pcv -> pcv.getRootValue()).collect(Collectors.toSet());
roots.forEach(root -> root.accept(oidExtractor));
Map<String, PolyString> oidNameMap = new HashMap<>();
List<String> batch = new ArrayList<>();
for (Iterator<String> iterator = oidsToResolve.iterator(); iterator.hasNext(); ) {
batch.add(iterator.next());
if (batch.size() >= MAX_OIDS_TO_RESOLVE_AT_ONCE || !iterator.hasNext()) {
Query query = session.getNamedQuery("resolveReferences");
query.setParameterList("oid", batch);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
@SuppressWarnings({ "unchecked", "raw" })
List<Map<String, Object>> results = query.list(); // returns oid + name
for (Map<String, Object> result : results) {
String oid = (String) result.get("0");
RPolyString name = (RPolyString) result.get("1");
oidNameMap.put(oid, new PolyString(name.getOrig(), name.getNorm()));
}
batch.clear();
}
}
if (!oidNameMap.isEmpty()) {
Visitor nameSetter = visitable -> {
if (visitable instanceof PrismReferenceValue) {
PrismReferenceValue value = (PrismReferenceValue) visitable;
if (value.getTargetName() == null && value.getOid() != null) {
value.setTargetName(oidNameMap.get(value.getOid()));
}
}
};
roots.forEach(root -> root.accept(nameSetter));
}
}
}