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 Jan 20, 2022
2 parents 07a9239 + af26192 commit 2691ef3
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.evolveum.midpoint.repo.sqale.jsonb.Jsonb;
import com.evolveum.midpoint.repo.sqale.jsonb.JsonbUtils;
import com.evolveum.midpoint.repo.sqale.qmodel.ext.MExtItem;
import com.evolveum.midpoint.repo.sqale.qmodel.ext.MExtItem.Key;
import com.evolveum.midpoint.repo.sqale.qmodel.ext.MExtItemCardinality;
import com.evolveum.midpoint.repo.sqale.qmodel.ext.MExtItemHolderType;
import com.evolveum.midpoint.repo.sqale.qmodel.object.MObjectType;
Expand All @@ -42,13 +43,22 @@ public Jsonb processExtensions(
if (extDef == null) {
continue; // item does not have definition, skipping
}

ExtItemInfo extItemInfo = findExtensionItem(extDef, holderType);
if (extItemInfo == null) {
continue; // not-indexed, skipping this item
}

Object value = extItemValue(item, extItemInfo);

extMap.put(extItemInfo.getId(), value);

// we may need to add add also single value index, if definition is dynamic
// see additionalSingleValueIndexNeeded javadoc for more information
if (additionalSingleValueIndexNeeded(item, extItemInfo)) {
addSingleValueIndex(extMap, item, holderType);
}

} catch (RuntimeException e) {
// If anything happens (like NPE in Map.of) we want to capture the "bad" item.
throw new SystemException(
Expand All @@ -59,6 +69,37 @@ public Jsonb processExtensions(
return Jsonb.fromMap(extMap);
}

/**
* Checks if additional single value index is needed
*
* If item contains single value and item definition is dynamic (eg. generated by parser),
* we do not know if known definition is single or multi value. During search definition
* is provided by provisioning - and contains multiplicity, this allows for both indexes
* (scalar and array) to be available for such search.
*
* Dynamic definition (instead of real definition) is usually present during direct manipulation
* of objects via repository APIs and not model APIs. Existence of both indexes in unknown
* states allows for search to work properly, once definition is known to search invoker.
*
* @param item Item to be added
* @param extItemInfo Originally determined item definition
* @return true if we also need to add single value index
*/
private boolean additionalSingleValueIndexNeeded(Item<?, ?> item, ExtItemInfo extItemInfo) {
return item.size() == 1
&& MExtItemCardinality.ARRAY.equals(extItemInfo.item.cardinality)
&& item.getDefinition().isDynamic();
}

private void addSingleValueIndex(Map<String, Object> extMap, Item<?,?> item, MExtItemHolderType holderType) {
ItemDefinition<?> extDef = item.getDefinition();
Key singleValueKey = MExtItem.keyFrom(extDef, holderType, MExtItemCardinality.SCALAR);
MExtItem singleValueExt = repositoryContext.resolveExtensionItem(singleValueKey);
ExtItemInfo singleInfo = extItemInfo(singleValueExt, extDef);
Object singleValue = extItemValue(item, singleInfo);
extMap.put(singleInfo.getId(), singleValue);
}

/** Returns ext item definition or null if the item is not indexed and should be skipped. */
@Nullable
public ExtensionProcessor.ExtItemInfo findExtensionItem(
Expand All @@ -71,12 +112,15 @@ public ExtensionProcessor.ExtItemInfo findExtensionItem(
// TODO review any need for shadow attributes, now they are stored fine, but the code here
// is way too simple compared to the old repo.

return extItemInfo(extItem, definition);
}

private ExtensionProcessor.ExtItemInfo extItemInfo(MExtItem extItem, ItemDefinition<?> definition) {
ExtItemInfo info = new ExtItemInfo();
info.item = extItem;
if (definition instanceof PrismReferenceDefinition) {
info.defaultRefTargetType = ((PrismReferenceDefinition) definition).getTargetTypeName();
}

return info;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,16 @@ public int hashCode() {

/** Creates ext item key from item definition and holder type. */
public static Key keyFrom(ItemDefinition<?> definition, MExtItemHolderType holderType) {
return keyFrom(definition, holderType,
definition.getMaxOccurs() == 1 ? MExtItemCardinality.SCALAR : MExtItemCardinality.ARRAY);
}

/** Creates ext item key from item definition and holder type. */
public static Key keyFrom(ItemDefinition<?> definition, MExtItemHolderType holderType, MExtItemCardinality cardinality) {
MExtItem.Key key = new MExtItem.Key();
key.itemName = QNameUtil.qNameToUri(definition.getItemName());
key.valueType = QNameUtil.qNameToUri(definition.getTypeName());
key.cardinality = definition.getMaxOccurs() == 1
? MExtItemCardinality.SCALAR : MExtItemCardinality.ARRAY;
key.cardinality = cardinality;
key.holderType = holderType;

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
Expand Down Expand Up @@ -143,17 +144,18 @@ public ShadowType toSchemaObject(Tuple row, QShadow entityPath,
GetOperationOptions rootOptions = SelectorOptions.findRootOptions(options);
if (GetOperationOptions.isRaw(rootOptions)) {
// If raw=true, we populate attributes with types cached in repository
applyShadowAttributesDefinitions(shadowType);
//return shadowType;
Jsonb rowAttributes = row.get(entityPath.attributes);
applyShadowAttributesDefinitions(shadowType, rowAttributes);
}

List<SelectorOptions<GetOperationOptions>> retrieveOptions = SelectorOptions.filterRetrieveOptions(options);
if (retrieveOptions.isEmpty()) {
return shadowType;
}

addIndexOnlyAttributes(shadowType, row, entityPath, retrieveOptions);

if (loadIndexOnly(retrieveOptions)) {
addIndexOnlyAttributes(shadowType, row, entityPath, retrieveOptions);
}
return shadowType;
}

Expand Down Expand Up @@ -203,7 +205,6 @@ private void addIndexOnlyAttributes(ShadowType shadowType, Tuple row,
}
}


@Override
public Collection<SelectorOptions<GetOperationOptions>> updateGetOptions(
Collection<SelectorOptions<GetOperationOptions>> options,
Expand All @@ -223,13 +224,12 @@ public Collection<SelectorOptions<GetOperationOptions>> updateGetOptions(
return ret;
}



@Override
public @NotNull Path<?>[] selectExpressions(QShadow entity,
Collection<SelectorOptions<GetOperationOptions>> options) {
var retrieveOptions = SelectorOptions.filterRetrieveOptions(options);
if (loadIndexOnly(retrieveOptions)) {
boolean isRaw = GetOperationOptions.isRaw(SelectorOptions.findRootOptions(options));
if (isRaw || loadIndexOnly(retrieveOptions)) {
return new Path[] { entity.oid, entity.fullObject, entity.attributes };
}
return new Path[] { entity.oid, entity.fullObject };
Expand All @@ -251,22 +251,40 @@ private boolean loadIndexOnly(List<SelectorOptions<GetOperationOptions>> retriev
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private void applyShadowAttributesDefinitions(ShadowType shadowType) throws SchemaException {
private void applyShadowAttributesDefinitions(ShadowType shadowType, Jsonb rowAttributes) throws SchemaException {
Map<QName, MExtItem> definitions = definitionsFrom(rowAttributes);

if (shadowType.getAttributes() == null) {
return;
}
PrismContainerValue<?> attributesOld = shadowType.getAttributes().asPrismContainerValue();
PrismContainerValue<?> attributes = shadowType.getAttributes().asPrismContainerValue();

for (Item<?, ?> attribute : attributesOld.getItems()) {
for (Item<?, ?> attribute : attributes.getItems()) {
ItemName itemName = attribute.getElementName();
MExtItem itemInfo = repositoryContext().getExtensionItem(
MExtItem.itemNameKey(attribute.getElementName(), MExtItemHolderType.ATTRIBUTES));
MExtItem itemInfo = definitions.get(itemName);
if (itemInfo != null && attribute.getDefinition() == null) {
((Item) attribute).applyDefinition(definitionFrom(itemName, itemInfo, false), true);
}
}
}

private Map<QName, MExtItem> definitionsFrom(Jsonb rowAttributes) {
Map<QName, MExtItem> definitions = new HashMap<>();
if (rowAttributes == null) {
return definitions;
}
Map<String, Object> attributes = Jsonb.toMap(rowAttributes);

for (String id : attributes.keySet()) {
var extItem = repositoryContext().getExtensionItem(Integer.valueOf(id));
if (extItem != null) {
QName key = QNameUtil.uriToQName(extItem.itemName);
definitions.put(key, extItem);
}
}
return definitions;
}

private ItemDefinition<?> definitionFrom(QName name, MExtItem itemInfo, boolean indexOnly) {
QName typeName = ExtUtils.getSupportedTypeName(itemInfo.valueType);
final MutableItemDefinition<?> def;
Expand Down

0 comments on commit 2691ef3

Please sign in to comment.