Skip to content

Commit

Permalink
repo-sqale: storing of extension values for enums, polys and refs + test
Browse files Browse the repository at this point in the history
  • Loading branch information
virgo47 committed Jun 9, 2021
1 parent 7781a9e commit f440b42
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;

import com.querydsl.core.Tuple;
Expand All @@ -19,6 +20,7 @@
import org.jetbrains.annotations.Nullable;

import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.repo.sqale.SqaleRepoContext;
import com.evolveum.midpoint.repo.sqale.delta.item.*;
import com.evolveum.midpoint.repo.sqale.filtering.ArrayPathItemFilterProcessor;
Expand Down Expand Up @@ -46,6 +48,7 @@
import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DisplayableValue;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
Expand Down Expand Up @@ -413,6 +416,7 @@ protected Jsonb processExtensions(Containerable extContainer, MExtItemHolderType
}
}

// supported types for extension properties, references ignore this
public static final Set<QName> SUPPORTED_INDEXED_EXTENSION_TYPES = Set.of(
DOMUtil.XSD_BOOLEAN,
DOMUtil.XSD_INT,
Expand All @@ -436,16 +440,21 @@ private MExtItem findExtensionItem(Item<?, ?> item, MExtItemHolderType holderTyp

if (definition instanceof PrismPropertyDefinition) {
Boolean indexed = ((PrismPropertyDefinition<?>) definition).isIndexed();
// null is default which is "indexed"
if (indexed != null && !indexed) {
return null;
}
// enum is recognized by having allowed values
Collection<? extends DisplayableValue<?>> allowedValues =
((PrismPropertyDefinition<?>) definition).getAllowedValues();
if (!SUPPORTED_INDEXED_EXTENSION_TYPES.contains(definition.getTypeName())
&& (allowedValues == null || allowedValues.isEmpty())) {
return null;
}
} else if (!(definition instanceof PrismReferenceDefinition)) {
throw new UnsupportedOperationException("Unknown definition type '"
+ definition + "', can't say if '" + item + "' is indexed or not.");
}
if (!SUPPORTED_INDEXED_EXTENSION_TYPES.contains(definition.getTypeName())) {
return null;
}
} // else it's reference which is indexed implicitly

return repositoryContext().resolveExtensionItem(MExtItem.keyFrom(definition, holderType));
}
Expand All @@ -468,10 +477,28 @@ private Object convertExtItemValue(Object realValue) {
|| realValue instanceof Boolean) {
return realValue;
}
// TODO enum
// TODO polystring
// TODO reference
// TODO datetime

if (realValue instanceof PolyString) {
PolyString poly = (PolyString) realValue;
return Map.of("o", poly.getOrig(),
"n", poly.getNorm());
}

if (realValue instanceof Referencable) {
Referencable ref = (Referencable) realValue;
return Map.of("o", ref.getOid(),
"t", processCacheableUri(ref.getType()),
"r", processCacheableRelation(ref.getRelation()));
}

if (realValue instanceof Enum) {
return realValue.toString();
}

if (realValue instanceof XMLGregorianCalendar) {
//noinspection ConstantConditions
return MiscUtil.asInstant((XMLGregorianCalendar) realValue).toString();
}

throw new IllegalArgumentException(
"Unsupported type '" + realValue.getClass() + "' for value '" + realValue + "'.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,15 @@ protected String cachedUriById(Integer uriId) {
return selectOne(qUri, qUri.id.eq(uriId)).uri;
}

protected Integer cachedUriId(QName qName) {
return cachedUriId(QNameUtil.qNameToUri(qName));
}

protected Integer cachedUriId(String uri) {
QUri qUri = QUri.DEFAULT;
return selectOne(qUri, qUri.uri.eq(uri)).id;
}

protected void assertCachedUri(Integer uriId, QName qName) {
assertCachedUri(uriId, QNameUtil.qNameToUri(qName));
}
Expand Down Expand Up @@ -256,18 +265,32 @@ protected PrismReferenceValue ref(String targetOid, QName relation) {
.createReferenceValue(targetOid).relation(relation);
}

protected PrismReferenceValue ref(String targetOid, QName targetType, QName relation) {
return prismContext.itemFactory()
.createReferenceValue(targetOid, targetType).relation(relation);
}

// region extension support
protected <V> void addExtensionValue(
Containerable extContainer, String itemName, V value) throws SchemaException {
PrismContainerValue<?> pcv = extContainer.asPrismContainerValue();
ItemDefinition<PrismProperty<V>> itemDefinition =
ItemDefinition<?> itemDefinition =
pcv.getDefinition().findItemDefinition(new ItemName(itemName));
assertThat(itemDefinition)
.withFailMessage("No definition found for item name '%s' in %s", itemName, pcv)
.isNotNull();
PrismProperty<V> property = itemDefinition.instantiate();
property.setRealValue(value);
pcv.add(property);
if (itemDefinition instanceof PrismReferenceDefinition) {
PrismReference ref = (PrismReference) itemDefinition.instantiate();
ref.add(value instanceof PrismReferenceValue
? (PrismReferenceValue) value
: ((Referencable) value).asReferenceValue());
pcv.add(ref);
} else {
//noinspection unchecked
PrismProperty<V> property = (PrismProperty<V>) itemDefinition.instantiate();
property.setRealValue(value);
pcv.add(property);
}
}

protected String extensionKey(Containerable extContainer, String itemName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.UUID;
Expand All @@ -26,6 +27,7 @@

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.repo.api.DeleteObjectResult;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.repo.sqale.SqaleRepoBaseTest;
Expand Down Expand Up @@ -702,6 +704,10 @@ public void test305AddObjectWithExtensionItemsOfVariousSimpleTypes()
addExtensionValue(extensionContainer, "float", Float.MAX_VALUE);
addExtensionValue(extensionContainer, "float-2", -Float.MIN_VALUE);
addExtensionValue(extensionContainer, "boolean", true);
addExtensionValue(extensionContainer, "enum", BeforeAfterType.AFTER);
Instant dateTime = Instant.now();
addExtensionValue(extensionContainer, "dateTime",
MiscUtil.asXMLGregorianCalendar(dateTime));

when("adding it to the repository");
String returnedOid = repositoryService.addObject(object.asPrismObject(), null, result);
Expand Down Expand Up @@ -738,10 +744,51 @@ public void test305AddObjectWithExtensionItemsOfVariousSimpleTypes()
new BigDecimal(Float.toString(Float.MAX_VALUE)).toBigInteger())
.containsEntry(extensionKey(extensionContainer, "float-2"),
new BigDecimal(Float.toString(-Float.MIN_VALUE)))
.containsEntry(extensionKey(extensionContainer, "boolean"), true);
.containsEntry(extensionKey(extensionContainer, "boolean"), true)
.containsEntry(extensionKey(extensionContainer, "enum"), "AFTER")
// Must be truncated to millis, because XML dateTime drops nanos.
.containsEntry(extensionKey(extensionContainer, "dateTime"),
dateTime.truncatedTo(ChronoUnit.MILLIS).toString());
// The different types are OK here, must be treated only for index-only extensions.
// In that case value must be converted to the expected target type; not part of this test.
}

@Test
public void test307AddObjectWithExtensionReferenceAndPolyString()
throws ObjectAlreadyExistsException, SchemaException, JsonProcessingException {
OperationResult result = createOperationResult();

given("object with extension reference and poly string");
String objectName = "user" + getTestNumber();
UserType object = new UserType(prismContext)
.name(objectName)
.extension(new ExtensionType(prismContext));
ExtensionType extensionContainer = object.getExtension();
addExtensionValue(extensionContainer, "poly", PolyString.fromOrig("poly-value"));
String targetOid = UUID.randomUUID().toString();
QName relation = QName.valueOf("{https://random.org/ns}random-rel-1");
addExtensionValue(extensionContainer, "ref", ref(targetOid,
UserType.COMPLEX_TYPE, relation));

when("adding it to the repository");
String returnedOid = repositoryService.addObject(object.asPrismObject(), null, result);

then("operation is successful and ext column stores the values as nested objects");
assertThatOperationResult(result).isSuccess();
assertThat(returnedOid).isEqualTo(object.getOid());

MUser row = selectObjectByOid(QUser.class, returnedOid);
assertThat(row.oid).isEqualTo(UUID.fromString(returnedOid));
assertThat(row.ext).isNotNull();
Map<String, Object> extMap = Jsonb.toMap(row.ext);
assertThat(extMap)
.containsEntry(extensionKey(extensionContainer, "poly"),
Map.of("o", "poly-value", "n", "polyvalue"))
.containsEntry(extensionKey(extensionContainer, "ref"),
Map.of("o", targetOid,
"t", cachedUriId(UserType.COMPLEX_TYPE),
"r", cachedUriId(relation)));
}
// endregion

// region insertion of various types
Expand Down Expand Up @@ -1588,7 +1635,8 @@ public void test850Case() throws Exception {
assertCachedUri(caseRow.targetRefRelationId, targetRelation);

QCaseWorkItem wiAlias = aliasFor(QCaseWorkItem.class);
List<MCaseWorkItem> wiRows = select(wiAlias, wiAlias.ownerOid.eq(UUID.fromString(acase.getOid())));
List<MCaseWorkItem> wiRows = select(wiAlias,
wiAlias.ownerOid.eq(UUID.fromString(acase.getOid())));
assertThat(wiRows).hasSize(2);
wiRows.sort(comparing(tr -> tr.cid));

Expand Down Expand Up @@ -1624,8 +1672,10 @@ public void test850Case() throws Exception {
assertCachedUri(wiRow.performerRefRelationId, performer2Relation);
assertThat(wiRow.stageNumber).isEqualTo(2);

QCaseWorkItemReference assigneeRefAlias = QCaseWorkItemReferenceMapping.getForCaseWorkItemAssignee().defaultAlias();
List<MCaseWorkItemReference> assigneeRefRows = select(assigneeRefAlias, assigneeRefAlias.ownerOid.eq(UUID.fromString(acase.getOid())));
QCaseWorkItemReference assigneeRefAlias =
QCaseWorkItemReferenceMapping.getForCaseWorkItemAssignee().defaultAlias();
List<MCaseWorkItemReference> assigneeRefRows = select(assigneeRefAlias,
assigneeRefAlias.ownerOid.eq(UUID.fromString(acase.getOid())));
assertThat(assigneeRefRows).hasSize(3);
assigneeRefRows.sort(comparing(tr -> tr.targetOid));

Expand Down Expand Up @@ -1656,8 +1706,10 @@ public void test850Case() throws Exception {
assertCachedUri(assigneeRefRow.relationId, wi1AssigneeRef1Relation);
assertThat(assigneeRefRow.workItemCid).isEqualTo(41);

QCaseWorkItemReference candidateRefAlias = QCaseWorkItemReferenceMapping.getForCaseWorkItemCandidate().defaultAlias();
List<MCaseWorkItemReference> candidateRefRows = select(candidateRefAlias, candidateRefAlias.ownerOid.eq(UUID.fromString(acase.getOid())));
QCaseWorkItemReference candidateRefAlias =
QCaseWorkItemReferenceMapping.getForCaseWorkItemCandidate().defaultAlias();
List<MCaseWorkItemReference> candidateRefRows = select(candidateRefAlias,
candidateRefAlias.ownerOid.eq(UUID.fromString(acase.getOid())));
assertThat(candidateRefRows).hasSize(3);
candidateRefRows.sort(comparing(tr -> tr.targetOid));

Expand Down

0 comments on commit f440b42

Please sign in to comment.