Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
skublik committed Aug 19, 2021
2 parents 33704b5 + 75d7e7d commit e0a36cf
Show file tree
Hide file tree
Showing 15 changed files with 951 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.List;
import javax.xml.namespace.QName;

import org.apache.commons.lang3.StringUtils;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.ContextConfiguration;
Expand Down Expand Up @@ -341,7 +342,8 @@ public void test200AddRole1AssignmentToDraftUser() throws Exception {
private OperationResult executeAssignRole1(String userOid, boolean immediate, boolean deputiesOfLeadOneSeeItems, String approverOid, QName relation,
boolean useInMemoryTracing) throws Exception {
PrismObject<UserType> user = getUser(userOid);
String userName = user.getName().getOrig();
String userDisplayName = user.asObjectable().getFullName() != null && StringUtils.isNotEmpty(user.asObjectable().getFullName().getOrig())
? user.asObjectable().getFullName().getOrig() : user.getName().getOrig();
// @formatter:off
ObjectDelta<UserType> delta = prismContext
.deltaFor(UserType.class)
Expand Down Expand Up @@ -390,7 +392,7 @@ protected String getObjectOid() {
@Override
protected List<ExpectedTask> getExpectedTasks() {
return singletonList(new ExpectedTask(getRoleOid(1), "Assigning role \"" +
getRoleName(1) + "\" to user \"" + userName + "\""));
getRoleName(1) + "\" to user \"" + userDisplayName + "\""));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ public void test350ApproveAsAttorneyAdministrator() throws Exception {
.workItems()
.assertWorkItems(1)
.single()
.assertNameOrig("Assigning role \"vault-access\" to user \"launchpad\"")
.assertNameOrig("Assigning role \"vault-access\" to user \"Launchpad McQuack\"")
.assertStageNumber(1)
.assertOriginalAssigneeRef(USER_SCROOGE.oid, UserType.COMPLEX_TYPE)
.assertPerformerRef(USER_SCROOGE.oid, UserType.COMPLEX_TYPE) // we should perhaps list attorney here as well
Expand Down Expand Up @@ -573,7 +573,7 @@ public void test360ApproveAsAttorneyGizmoduck() throws Exception {

assertCase(approvalCase, "after")
.display()
.assertNameOrig("Assigning role \"vault-access\" to user \"launchpad\"")
.assertNameOrig("Assigning role \"vault-access\" to user \"Launchpad McQuack\"")
.assertApprovalCaseArchetype()
.assertObjectRef(USER_LAUNCHPAD.oid, UserType.COMPLEX_TYPE)
.assertTargetRef(ROLE_VAULT_ACCESS.oid, RoleType.COMPLEX_TYPE)
Expand All @@ -594,7 +594,7 @@ public void test360ApproveAsAttorneyGizmoduck() throws Exception {
.workItems()
.assertWorkItems(1)
.single()
.assertNameOrig("Assigning role \"vault-access\" to user \"launchpad\"")
.assertNameOrig("Assigning role \"vault-access\" to user \"Launchpad McQuack\"")
.assertStageNumber(1)
.assertOriginalAssigneeRef(USER_SCROOGE.oid, UserType.COMPLEX_TYPE)
.assertPerformerRef(USER_SCROOGE.oid, UserType.COMPLEX_TYPE) // we should perhaps list attorney here as well
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ private <S extends ObjectType> S readByOid(
repositoryContext.getMappingBySchemaType(schemaType);
QObject<MObject> root = rootMapping.defaultAlias();

Tuple result = repositoryContext.newQuery(jdbcSession.connection())
Tuple result = jdbcSession.newQuery()
.from(root)
.select(rootMapping.selectExpressions(root, options))
.where(root.oid.eq(oid))
Expand All @@ -230,7 +230,7 @@ private <S extends ObjectType> S readByOid(
throw new ObjectNotFoundException(schemaType, oid.toString());
}

return rootMapping.toSchemaObject(result, root, options);
return rootMapping.toSchemaObject(result, root, options, jdbcSession, false);
}

@Override
Expand Down Expand Up @@ -562,7 +562,7 @@ RootUpdateContext<S, Q, R> prepareUpdateContext(
repositoryContext.getMappingBySchemaType(schemaType);
QObject<R> entityPath = rootMapping.defaultAlias();

Tuple result = repositoryContext.newQuery(jdbcSession.connection())
Tuple result = jdbcSession.newQuery()
.select(entityPath.oid, entityPath.fullObject, entityPath.containerIdSeq)
.from(entityPath)
.where(entityPath.oid.eq(oid))
Expand All @@ -573,7 +573,7 @@ RootUpdateContext<S, Q, R> prepareUpdateContext(
throw new ObjectNotFoundException(schemaType, oid.toString());
}

S object = rootMapping.toSchemaObject(result, entityPath, Collections.emptyList());
S object = rootMapping.toSchemaObject(result, entityPath, Collections.emptyList(), jdbcSession, true);

R rootRow = rootMapping.newRowObject();
rootRow.oid = oid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void deleteValues(Collection<T> values) {
private void deleteContainer(Q c, T container) {
context.jdbcSession().newDelete(c)
.where(c.isOwnedBy(context.row())
.and(c.cid.eq(container.asPrismContainerValue().getId())))
.and(containerTableMapping.containerIdentityPredicate(c, container)))
.execute();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContainerDefinition;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
Expand Down Expand Up @@ -39,6 +40,10 @@ public ExtensionItemDeltaProcessor(
@Override
public void process(ItemDelta<?, ?> modification) throws RepositoryException, SchemaException {
ItemPath itemPath = modification.getPath();
if (modification.getDefinition() instanceof PrismContainerDefinition<?>) {
return; // We do not index containers
}

Item<PrismValue, ?> item = context.findValueOrItem(itemPath);
Collection<?> realValues = item != null ? item.getRealValues() : null;
ItemDefinition<?> definition = modification.getDefinition();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import com.evolveum.midpoint.repo.sqale.qmodel.ref.MReference;
import com.evolveum.midpoint.repo.sqale.qmodel.ref.QReferenceMapping;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.RepositoryException;
import com.evolveum.midpoint.repo.sqlbase.RepositoryObjectParseResult;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.EnumItemFilterProcessor;
import com.evolveum.midpoint.repo.sqlbase.filtering.item.PolyStringItemFilterProcessor;
Expand Down Expand Up @@ -470,4 +469,9 @@ protected Collection<? extends QName> fullObjectItemsToSkip() {
// TODO extend later, things like FocusType.F_JPEG_PHOTO, see ObjectUpdater#updateFullObject
return Collections.emptyList();
}

public S toSchemaObject(Tuple result, Q root,
Collection<SelectorOptions<GetOperationOptions>> options, @NotNull JdbcSession jdbcSession, boolean forceFull) throws SchemaException {
return toSchemaObject(result, root, options);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.evolveum.midpoint.repo.sqale.mapping.SqaleTableMapping;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.querydsl.core.types.Predicate;

/**
* Mapping between {@link QContainer} and {@link Containerable}.
Expand Down Expand Up @@ -87,4 +88,8 @@ public R initRowObject(S schemaObject, OR ownerRow) {
public R insert(S schemaObject, OR ownerRow, JdbcSession jdbcSession) throws SchemaException {
throw new UnsupportedOperationException("Missing insert() implementation in " + getClass());
}

public Predicate containerIdentityPredicate(Q entityPath, S container) {
return entityPath.cid.eq(container.asPrismContainerValue().getId());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,36 @@

import static com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType.F_ROW;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import javax.xml.namespace.QName;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.repo.sqale.SqaleRepoContext;
import com.evolveum.midpoint.repo.sqale.qmodel.object.QAssignmentHolderMapping;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.QueryException;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.ObjectSelector;
import com.evolveum.midpoint.schema.RelationalValueSearchQuery;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableType;
import com.google.common.base.Strings;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.StringPath;
import com.querydsl.sql.SQLQuery;

/**
* Mapping between {@link QLookupTable} and {@link LookupTableType}.
Expand Down Expand Up @@ -74,4 +93,115 @@ public void storeRelatedEntities(
QLookupTableRowMapping.get().insert(row, lookupTable, jdbcSession));
}
}

@Override
protected Collection<? extends QName> fullObjectItemsToSkip() {
return Collections.singleton(F_ROW);
}

@Override
public LookupTableType toSchemaObject(Tuple row, QLookupTable entityPath,
Collection<SelectorOptions<GetOperationOptions>> options, JdbcSession session, boolean forceFull) throws SchemaException {
LookupTableType base = super.toSchemaObject(row, entityPath, options);

if (forceFull || SelectorOptions.hasToLoadPath(F_ROW, options)) {
@Nullable GetOperationOptions rowOptions = findLookupTableGetOption(options);
appendLookupTableRows(row.get(0, UUID.class), base, rowOptions, session);
}

return base;
}

private void appendLookupTableRows(UUID ownerOid, LookupTableType base, GetOperationOptions rowOptions,
JdbcSession session) {
try {
RelationalValueSearchQuery queryDef = rowOptions == null ? null : rowOptions.getRelationalValueSearchQuery();
QLookupTableRowMapping rowMapping = QLookupTableRowMapping.get();
QLookupTableRow alias = rowMapping.defaultAlias();


BooleanExpression whereQuery = appendConditions(alias, alias.ownerOid.eq(ownerOid), queryDef);
SQLQuery<MLookupTableRow> query = session.newQuery()
.from(alias)
.select(alias)
.where(whereQuery);

query = paging(query, queryDef);

List<MLookupTableRow> result = query.fetch();

for (MLookupTableRow r : result) {
LookupTableRowType lookupRow = new LookupTableRowType().key(r.key);
if (r.labelOrig != null || r.labelNorm != null) {
lookupRow.label(PolyString.toPolyStringType(new PolyString(r.labelOrig, r.labelNorm)));
}
lookupRow.lastChangeTimestamp(MiscUtil.asXMLGregorianCalendar(r.lastChangeTimestamp));
lookupRow.value(r.value);
lookupRow.asPrismContainerValue().setId(r.cid);
base.getRow().add(lookupRow);
}
} catch (QueryException e) {
throw new SystemException("Unable to fetch nested table rows", e);
}
}

private BooleanExpression appendConditions(QLookupTableRow alias, BooleanExpression base, RelationalValueSearchQuery queryDef) throws QueryException {
if (queryDef == null || queryDef.getColumn() == null || queryDef.getSearchType() == null || Strings.isNullOrEmpty(queryDef.getSearchValue())) {
return base;
}
String value = queryDef.getSearchValue();
StringPath path = (StringPath) QLookupTableRowMapping.get().getItemMapper(queryDef.getColumn()).itemOrdering(alias, null);
BooleanExpression right;
if (LookupTableRowType.F_LABEL.equals(queryDef.getColumn())) {
path = alias.labelNorm;
var poly = new PolyString(value);
poly.recompute(prismContext().getDefaultPolyStringNormalizer());
value = poly.getNorm();
}

switch (queryDef.getSearchType()) {
case EXACT:
right = path.eq(value);
break;
case STARTS_WITH:
right = path.startsWith(value);
break;
case SUBSTRING:
right = path.contains(value);
break;
default:
throw new IllegalStateException();
}
return base.and(right);
}

private <R> SQLQuery<R> paging(SQLQuery<R> query, RelationalValueSearchQuery queryDef) {
if (queryDef != null && queryDef.getPaging() != null) {
var paging = queryDef.getPaging();
if (paging.getOffset() != null) {
query = query.offset(paging.getOffset());
}
if (paging.getMaxSize() != null) {
query = query.limit(paging.getMaxSize());
}
}
return query;
}

private GetOperationOptions findLookupTableGetOption(Collection<SelectorOptions<GetOperationOptions>> options) {
Collection<SelectorOptions<GetOperationOptions>> filtered = SelectorOptions.filterRetrieveOptions(options);
for (SelectorOptions<GetOperationOptions> option : filtered) {
ObjectSelector selector = option.getSelector();
if (selector == null) {
// Ignore this. These are top-level options. There will not
// apply to lookup table
continue;
}
if (LookupTableType.F_ROW.equivalent(selector.getPath())) {
return option.getOptions();
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@
import java.util.Objects;

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.repo.sqale.SqaleRepoContext;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainerMapping;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.mapping.TableRelationResolver;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.LookupTableRowType;
import com.querydsl.core.QueryFlag.Position;
import com.querydsl.core.types.Predicate;

/**
* Mapping between {@link QLookupTableRow} and {@link LookupTableRowType}.
Expand Down Expand Up @@ -77,10 +78,26 @@ public MLookupTableRow newRowObject(MLookupTable ownerRow) {
return row;
}


@Override
protected void insert(MLookupTableRow row, JdbcSession jdbcSession) {
// This is bit weird, but according to https://docs.evolveum.com/midpoint/devel/guides/development-with-lookuptable/
// Insert into lookup table is actually insert or replace based on key
jdbcSession.newInsert(defaultAlias())
.populate(row)
// QueryDSL does not support PostgreSQL syntax for upsert so it needs to be added as positional flag at the end of query
.addFlag(Position.END, " ON CONFLICT (owneroid, key)"
+" DO UPDATE SET "
+ " value = EXCLUDED.value,"
+ " labelOrig = EXCLUDED.labelOrig,"
+ " labelNorm = EXCLUDED.labelNorm,"
+ " lastChangeTimestamp = EXCLUDED.lastChangeTimestamp")
.execute();
}

@Override
public MLookupTableRow insert(LookupTableRowType lookupTableRow,
MLookupTable ownerRow, JdbcSession jdbcSession) {

MLookupTableRow row = initRowObject(lookupTableRow, ownerRow);
row.key = lookupTableRow.getKey();
row.value = lookupTableRow.getValue();
Expand All @@ -90,4 +107,15 @@ public MLookupTableRow insert(LookupTableRowType lookupTableRow,
insert(row, jdbcSession);
return row;
}

@Override
public Predicate containerIdentityPredicate(QLookupTableRow entityPath, LookupTableRowType container) {
if (container.getId() != null) {
return super.containerIdentityPredicate(entityPath, container);
}
if (container.getKey() != null) {
return entityPath.key.eq(container.getKey());
}
throw new IllegalArgumentException("id or key must be specified for lookup table row");
}
}

0 comments on commit e0a36cf

Please sign in to comment.