Skip to content

Commit

Permalink
sqale: Added support for resolveNames
Browse files Browse the repository at this point in the history
  • Loading branch information
tonydamage committed Sep 6, 2021
1 parent 677159b commit d83d8f7
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright (C) 2010-2021 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.repo.sqale.mapping;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.Visitor;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.ItemPathCollectionsUtil;
import com.evolveum.midpoint.prism.path.UniformItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.repo.sqale.SqaleUtils;
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObject;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObject;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.querydsl.core.Tuple;

public abstract class ReferenceNameResolver {

protected abstract <S> S resolve(S object, JdbcSession session);

public static ReferenceNameResolver from(Collection<SelectorOptions<GetOperationOptions>> options) {
@NotNull
List<? extends ItemPath> paths = getPathsToResolve(options);
if(paths.isEmpty()) {
return new Noop();
}
return new Impl(paths);
}

@NotNull
private static List<? extends ItemPath> getPathsToResolve(Collection<SelectorOptions<GetOperationOptions>> options) {
final UniformItemPath emptyPath = PrismContext.get().emptyPath();
List<UniformItemPath> rv = new ArrayList<>();
if (options == null || options.isEmpty()) {
return rv;
}
for (SelectorOptions<GetOperationOptions> option : options) {
if (GetOperationOptions.isResolveNames(option.getOptions())) {
rv.add(option.getItemPath(emptyPath));
}
}
return rv;
}

private static final class Noop extends ReferenceNameResolver {

@Override
protected <S> S resolve(S object, JdbcSession session) {
return object;
}
}

private static final class Impl extends ReferenceNameResolver {

private final List<? extends ItemPath> paths;
private final Map<UUID, PolyString> uuidToName = new HashMap<>();
private final Set<UUID> oidsToResolve = new HashSet<>();

public Impl(List<? extends ItemPath> paths) {
super();
this.paths = paths;
}

@Override
protected <S> S resolve(S object, JdbcSession session) {
if (!(object instanceof Containerable)) {
return object;
}
PrismContainerValue<?> container = ((Containerable) object).asPrismContainerValue();
Visitor initialWalk = visitable -> {
if (visitable instanceof PrismReferenceValue) {
initialVisit((PrismReferenceValue) visitable);
}
};
container.accept(initialWalk);
resolveNames(session);
Visitor updater = visitable -> {
if (visitable instanceof PrismReferenceValue) {
updateReference((PrismReferenceValue) visitable);
}
};
container.accept(updater);
return object;
}



private void resolveNames(JdbcSession session) {
QObject<MObject> object = new QObject<>(MObject.class, "obj");
// TODO: Add batch processing
if(oidsToResolve.isEmpty()) {
return;
}

List<Tuple> namesResult = session.newQuery()
.from(object)
.select(object.oid, object.nameOrig, object.nameNorm)
.where(object.oid.in(oidsToResolve))
.fetch();
for (Tuple named : namesResult) {
UUID uuid = named.get(object.oid);
oidsToResolve.remove(uuid);
String orig = named.get(object.nameOrig);
String norm = named.get(object.nameNorm);
PolyString poly = new PolyString(orig, norm);
uuidToName.put(uuid, poly);
}
}

private void initialVisit(PrismReferenceValue value) {
if (!ItemPathCollectionsUtil.containsSubpathOrEquivalent(paths, value.getPath())) {
return;
}
if (value.getTargetName() != null) {
return;
}
if (value.getObject() != null) {
value.setTargetName(value.getObject().getName());
return;
}
if (value.getOid() == null) {
return;
}
UUID oid = SqaleUtils.oidToUUid(value.getOid());
PolyString maybe = uuidToName.get(oid);
if (maybe != null) {
value.setTargetName(maybe);
} else {
oidsToResolve .add(oid);
}
}

private void updateReference(PrismReferenceValue value) {
if (value.getOid() == null) {
return;
}
PolyString name = uuidToName.get(SqaleUtils.oidToUUid(value.getOid()));
if (name != null) {
value.setTargetName(name);
}
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReferenceMapping;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.RepositoryObjectParseResult;
import com.evolveum.midpoint.repo.sqlbase.SqlQueryContext;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.EnumItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.PolyStringItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.SimpleItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.TimestampItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.mapping.ItemSqlMapper;
import com.evolveum.midpoint.repo.sqlbase.mapping.QueryTableMapping;
import com.evolveum.midpoint.repo.sqlbase.mapping.RepositoryMappingException;
import com.evolveum.midpoint.repo.sqlbase.mapping.ResultListRowTransformer;
import com.evolveum.midpoint.repo.sqlbase.querydsl.FlexibleRelationalPathBase;
import com.evolveum.midpoint.repo.sqlbase.querydsl.UuidPath;
import com.evolveum.midpoint.schema.GetOperationOptions;
Expand Down Expand Up @@ -513,6 +516,28 @@ public S toSchemaObject(
Collection<SelectorOptions<GetOperationOptions>> options,
@NotNull JdbcSession jdbcSession,
boolean forceFull) throws SchemaException {
return toSchemaObject(result, root, options);
S ret = toSchemaObject(result, root, options);
ret = resolveNames(ret, jdbcSession, options);
return ret;

}



public S resolveNames(S object, JdbcSession session, Collection<SelectorOptions<GetOperationOptions>> options) {
// FIXME: This should be session visible
return ReferenceNameResolver.from(options).resolve(object, session);
}

@Override
public ResultListRowTransformer<S, Q, R> createRowTransformer(SqlQueryContext<S, Q, R> sqlQueryContext,
JdbcSession jdbcSession) {
return (tuple, entityPath, options) -> {
try {
return toSchemaObject(tuple, entityPath, options, jdbcSession, false);
} catch (SchemaException e) {
throw new RepositoryMappingException(e);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

import static com.evolveum.midpoint.prism.PrismConstants.T_OBJECT_REFERENCE;
Expand All @@ -32,7 +33,10 @@
import com.evolveum.midpoint.prism.Containerable;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.Visitor;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.ObjectFilter;
Expand All @@ -49,6 +53,7 @@
import com.evolveum.midpoint.repo.sqale.qmodel.object.QObject;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.PolyStringItemFilterProcessor;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SchemaService;
import com.evolveum.midpoint.schema.SearchResultList;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
Expand Down Expand Up @@ -1956,6 +1961,22 @@ public void test960SearchByAxiomQueryLanguage() throws SchemaException {
.containsExactlyInAnyOrder(user3Oid, user4Oid);
}

@Test
public void test960SearchGetNames() throws SchemaException {
var options = SchemaService.get().getOperationOptionsBuilder().resolveNames().build();
ObjectQuery query = PrismContext.get().queryFor(FocusType.class).all().build();
SearchResultList<FocusType> result = searchObjects(FocusType.class, query, createOperationResult(), options.iterator().next());
assertNotNull(result);
Visitor check = visitable -> {
if (visitable instanceof PrismReferenceValue) {
assertNotNull(((PrismReferenceValue) visitable).getTargetName(), "TargetName should be set.");
}
};
for(FocusType obj : result) {
obj.asPrismObject().accept(check);
}
}

@Test
public void test970IsAncestor() throws Exception {
OperationResult operationResult = createOperationResult();
Expand Down

0 comments on commit d83d8f7

Please sign in to comment.