Skip to content

Commit

Permalink
QFocusIdentityMapping fullObject update after modify fix + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed Aug 2, 2022
1 parent 8f96fb6 commit c97ca31
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,10 @@ default SqaleMappingMixin<S, Q, R> addExtensionMapping(
return this;
}

/** Method called from `SqaleUpdateContext.finishExecutionOwn()` for containers. */
/**
* Method called from `SqaleUpdateContext.finishExecutionOwn()` for containers.
* This can be handy when more than just column set is required, e.g. to refresh fullObject, etc.
*/
default void afterModify(SqaleUpdateContext<S, Q, R> updateContext) throws SchemaException {
// nothing by default
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2021 Evolveum and contributors
* Copyright (C) 2010-2022 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
Expand Down Expand Up @@ -218,6 +218,19 @@ public MAccessCertificationCase insert(AccessCertificationCaseType acase,
return row;
}

private void storeWorkItems(
@NotNull MAccessCertificationCase caseRow,
@NotNull AccessCertificationCaseType schemaObject,
@NotNull JdbcSession jdbcSession) {

List<AccessCertificationWorkItemType> wis = schemaObject.getWorkItem();
if (!wis.isEmpty()) {
for (AccessCertificationWorkItemType wi : wis) {
QAccessCertificationWorkItemMapping.get().insert(wi, caseRow, jdbcSession);
}
}
}

@Override
public void afterModify(
SqaleUpdateContext<AccessCertificationCaseType, QAccessCertificationCase, MAccessCertificationCase> updateContext)
Expand All @@ -232,19 +245,6 @@ public void afterModify(
updateContext.set(updateContext.entityPath().fullObject, fullObject);
}

public void storeWorkItems(
@NotNull MAccessCertificationCase caseRow,
@NotNull AccessCertificationCaseType schemaObject,
@NotNull JdbcSession jdbcSession) throws SchemaException {

List<AccessCertificationWorkItemType> wis = schemaObject.getWorkItem();
if (!wis.isEmpty()) {
for (AccessCertificationWorkItemType wi : wis) {
QAccessCertificationWorkItemMapping.get().insert(wi, caseRow, jdbcSession);
}
}
}

@Override
public ResultListRowTransformer<AccessCertificationCaseType, QAccessCertificationCase, MAccessCertificationCase> createRowTransformer(
SqlQueryContext<AccessCertificationCaseType, QAccessCertificationCase, MAccessCertificationCase> sqlQueryContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.PrismConstants;
import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.repo.sqale.ExtensionProcessor;
import com.evolveum.midpoint.repo.sqale.SqaleRepoContext;
import com.evolveum.midpoint.repo.sqale.jsonb.Jsonb;
import com.evolveum.midpoint.repo.sqale.qmodel.common.QContainerMapping;
import com.evolveum.midpoint.repo.sqale.qmodel.ext.MExtItemHolderType;
import com.evolveum.midpoint.repo.sqale.update.SqaleUpdateContext;
import com.evolveum.midpoint.repo.sqlbase.JdbcSession;
import com.evolveum.midpoint.repo.sqlbase.mapping.TableRelationResolver;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusIdentityItemsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusIdentitySourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusIdentityType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

/**
* Mapping between {@link QFocusIdentity} and {@link FocusIdentityType}.
Expand Down Expand Up @@ -132,17 +132,32 @@ public FocusIdentityType toSchemaObject(MFocusIdentity row) throws SchemaExcepti
"identity for " + row.ownerOid + "," + row.cid,
FocusIdentityType.class);

// beginItems() replaces incomplete container from fullObject, which is good here.
FocusIdentityItemsType focusIdentityItems = identity.beginItems();
if (row.itemsOriginal != null) {
Map<String, Object> itemMap = Jsonb.toMap(row.itemsOriginal);
new ExtensionProcessor(repositoryContext()).extensionsToContainer(itemMap, focusIdentityItems.beginOriginal());
}
if (row.itemsNormalized != null) {
Map<String, Object> itemMap = Jsonb.toMap(row.itemsNormalized);
new ExtensionProcessor(repositoryContext()).extensionsToContainer(itemMap, focusIdentityItems.beginNormalized());
// begin/setItems() replaces incomplete container from fullObject, which is the right thing here.
if (row.itemsOriginal != null || row.itemsNormalized != null) {
FocusIdentityItemsType focusIdentityItems = identity.beginItems();
if (row.itemsOriginal != null) {
Map<String, Object> itemMap = Jsonb.toMap(row.itemsOriginal);
new ExtensionProcessor(repositoryContext()).extensionsToContainer(itemMap, focusIdentityItems.beginOriginal());
}
if (row.itemsNormalized != null) {
Map<String, Object> itemMap = Jsonb.toMap(row.itemsNormalized);
new ExtensionProcessor(repositoryContext()).extensionsToContainer(itemMap, focusIdentityItems.beginNormalized());
}
} else {
identity.setItems(null);
}

return identity;
}

@Override
public void afterModify(SqaleUpdateContext<FocusIdentityType, QFocusIdentity<OR>, MFocusIdentity> updateContext)
throws SchemaException {
PrismContainer<FocusIdentityType> identityContainer =
updateContext.findValueOrItem(FocusType.F_IDENTITIES, FocusIdentitiesType.F_IDENTITY);
// row in context already knows its CID
PrismContainerValue<FocusIdentityType> pcv = identityContainer.findValue(updateContext.row().cid);
byte[] fullObject = createFullObject(pcv.asContainerable());
updateContext.set(updateContext.entityPath().fullObject, fullObject);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,18 +164,20 @@ protected final void finishExecution() throws SchemaException, RepositoryExcepti

protected abstract void finishExecutionOwn() throws SchemaException, RepositoryException;

public final <O> O findValueOrItem(@NotNull Object... path) {
return findValueOrItem(ItemPath.create(path));
}

public <O> O findValueOrItem(@NotNull ItemPath path) {
if (parentContext == null) {
throw new UnsupportedOperationException(
"findItem() is unsupported on non-root update context");
throw new AssertionError("findItem() has special implementation for root update context");
}
return parentContext.findValueOrItem(path);
}

public boolean isOverwrittenId(Long id) {
if (parentContext == null) {
throw new UnsupportedOperationException(
"findItem() is unsupported on non-root update context");
throw new AssertionError("isOverwrittenId() has special implementation for root update context");
}
return parentContext.isOverwrittenId(id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,38 @@
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.repo.sqale.SqaleRepoBaseTest;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.MFocusIdentity;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.QFocusIdentity;
import com.evolveum.midpoint.repo.sqale.qmodel.focus.QFocusIdentityMapping;
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SchemaService;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.tools.testng.AlphabeticMethodExecutionRequired;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.exception.CommonException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

// TEMPORARY CODE
@AlphabeticMethodExecutionRequired
public class SqaleRepoIdentityDataTest extends SqaleRepoBaseTest {

public static final File TEST_DIR = new File("src/test/resources/identity");

private static final File FILE_USER_WITH_IDENTITY_DATA = new File(TEST_DIR, "user-with-identity-data.xml");

private static Collection<SelectorOptions<GetOperationOptions>> getWithIdentitiesOptions;

private String userOid;

@BeforeClass
Expand All @@ -45,6 +53,10 @@ public void initObjects() {
// TODO

assertThatOperationResult(result).isSuccess();

getWithIdentitiesOptions = SchemaService.get().getOperationOptionsBuilder()
.item(FocusType.F_IDENTITIES).retrieve()
.build();
}

@Test
Expand Down Expand Up @@ -78,10 +90,9 @@ public void test110GetUserByDefaultDoesNotLoadIdentityData() throws CommonExcept
@Test
public void test115GetUserWithRetrieveOptions() throws CommonException {
when("user is obtained with retrieve options for identities");
Collection<SelectorOptions<GetOperationOptions>> getOptions = SchemaService.get()
.getOperationOptionsBuilder().item(FocusType.F_IDENTITIES).retrieve().build();
OperationResult getWithIdentitiesResult = createOperationResult();
UserType user2 = repositoryService.getObject(UserType.class, userOid, getOptions, getWithIdentitiesResult).asObjectable();
UserType user2 = repositoryService.getObject(UserType.class, userOid,
getWithIdentitiesOptions, getWithIdentitiesResult).asObjectable();
assertThatOperationResult(getWithIdentitiesResult).isSuccess();

then("identities are complete and contain all the details");
Expand Down Expand Up @@ -112,9 +123,6 @@ public void test115GetUserWithRetrieveOptions() throws CommonException {

@Test
public void test200SearchUsingFuzzyMatching() throws CommonException {
when("user is obtained with retrieve options for identities");
Collection<SelectorOptions<GetOperationOptions>> getOptions = SchemaService.get()
.getOperationOptionsBuilder().item(FocusType.F_IDENTITIES).retrieve().build();
OperationResult result = createOperationResult();
ItemName familyNameQName = new ItemName(SchemaConstants.NS_C, "familyName");
var def = PrismContext.get().definitionFactory().createPropertyDefinition(familyNameQName, DOMUtil.XSD_STRING, null, null);
Expand All @@ -129,9 +137,79 @@ public void test200SearchUsingFuzzyMatching() throws CommonException {
familyNameQName)
.eq("green") // TODO was alice, do you want givenName query?
.build();
var ret = repositoryService.searchObjects(UserType.class, query, null, result); // TODO use options and assert?
var ret = repositoryService.searchObjects(UserType.class, query, null, result); // TODO use retrieve options and assert?
assertThat(ret.size()).isEqualTo(1);
}

// TODO modification test + hopefully updateGetOptions in QFocusMapping does the trick
@Test
public void test300ModifyAddIdentityContainer() throws CommonException {
OperationResult result = createOperationResult();

given("delta adding focus identity value");
ObjectDelta<UserType> delta = prismContext.deltaFor(UserType.class)
.item(UserType.F_IDENTITIES, FocusIdentitiesType.F_IDENTITY)
.add(new FocusIdentityType()
.source(new FocusIdentitySourceType()
.tag("test300")))
.asObjectDelta(userOid);

when("modifyObject is called");
repositoryService.modifyObject(UserType.class, userOid, delta.getModifications(), result);

then("operation is successful");
assertThatOperationResult(result).isSuccess();

and("new focus identity row is added");
QFocusIdentity<?> fi = QFocusIdentityMapping.get().defaultAlias();
List<MFocusIdentity> fiRows = select(fi, fi.ownerOid.eq(UUID.fromString(userOid)));
assertThat(fiRows).hasSize(3);

and("getObject without identity options still has no identities");
UserType user = repositoryService.getObject(UserType.class, userOid, null, result)
.asObjectable();
assertThat(user.asPrismObject().findContainer(FocusType.F_IDENTITIES).isIncomplete()).isTrue();

and("getObject returns focus with three identities");
user = repositoryService.getObject(UserType.class, userOid, getWithIdentitiesOptions, result)
.asObjectable();
assertThat(user.getIdentities().getIdentity())
.filteredOn(i -> i.getSource() != null && "test300".equals(i.getSource().getTag()))
.singleElement()
.extracting(i -> i.getItems())
.isNull();
}

@Test
public void test310ModifyReplaceItemInIdentityContainer() throws CommonException {
OperationResult result = createOperationResult();

given("delta adding focus identity value");
ObjectDelta<UserType> delta = prismContext.deltaFor(UserType.class)
// 3 is container ID for identity PCV added in test300
.item(UserType.F_IDENTITIES, FocusIdentitiesType.F_IDENTITY, 3L,
FocusIdentityType.F_SOURCE, FocusIdentitySourceType.F_TAG)
.replace("test310")
.asObjectDelta(userOid);

when("modifyObject is called");
repositoryService.modifyObject(UserType.class, userOid, delta.getModifications(), result);

then("operation is successful");
assertThatOperationResult(result).isSuccess();

and("getObject without identity options still has no identities");
UserType user = repositoryService.getObject(UserType.class, userOid, null, result)
.asObjectable();
assertThat(user.asPrismObject().findContainer(FocusType.F_IDENTITIES).isIncomplete()).isTrue();

and("getObject returns focus with three identities");
user = repositoryService.getObject(UserType.class, userOid, getWithIdentitiesOptions, result)
.asObjectable();
assertThat(user.getIdentities().getIdentity())
.filteredOn(i -> i.getSource() != null && "test310".equals(i.getSource().getTag()))
.singleElement()
.matches(i -> i.getId().equals(3L));
}

// TODO modification test inside items, check JSONB
}

0 comments on commit c97ca31

Please sign in to comment.