Skip to content

Commit

Permalink
Improve attribute analysis for role-mining
Browse files Browse the repository at this point in the history
1. Load extension attribute for attribute analysis
 with different types:
 Integer, Long, Boolean, Double, String, PolyString
 and ObjectReferenceType.
  • Loading branch information
tchrapovic committed Apr 15, 2024
1 parent c1a4d53 commit 27d3161
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
package com.evolveum.midpoint.common.mining.objects.analysis;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import com.evolveum.midpoint.prism.Item;
Expand All @@ -20,6 +22,8 @@
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;

import org.jetbrains.annotations.NotNull;

public class RoleAnalysisAttributeDef implements Serializable {

ItemPath path;
Expand Down Expand Up @@ -59,10 +63,6 @@ public RoleAnalysisAttributeDef(ItemPath path,
this.identifierType = identifierType;
}

public void calculateZScore(int objectWithExactAttributeCount, RoleAnalysisAttributeDef attributeDef) {
// TODO
}

public ItemPath getPath() {
return path;
}
Expand All @@ -87,7 +87,7 @@ public void setDisplayValue(String displayValue) {
this.displayValue = displayValue;
}

public String resolveSingleValueItem(PrismObject<?> prismObject, ItemPath itemPath) {
public String resolveSingleValueItem(@NotNull PrismObject<?> prismObject, @NotNull ItemPath itemPath) {
if (!isContainer) {
Item<PrismValue, ItemDefinition<?>> property = prismObject.findItem(itemPath);
if (property != null) {
Expand All @@ -98,11 +98,19 @@ public String resolveSingleValueItem(PrismObject<?> prismObject, ItemPath itemPa
return null;
}

public Set<String> resolveMultiValueItem(PrismObject<?> prismObject, ItemPath itemPath) {
return null;
public @NotNull Set<String> resolveMultiValueItem(@NotNull PrismObject<?> prismObject, @NotNull ItemPath itemPath) {
Set<String> resolvedValues = new HashSet<>();
Collection<Item<?, ?>> allItems = prismObject.getAllItems(itemPath);
for (Item<?, ?> item : allItems) {
Object realValue = item.getRealValue();
if (realValue != null) {
resolvedValues.add(realValue.toString());
}
}
return resolvedValues;
}

protected static String extractRealValue(Object object) {
public static String extractRealValue(Object object) {
if (object != null) {
if (object instanceof PolyString) {
return ((PolyString) object).getOrig();
Expand Down Expand Up @@ -130,10 +138,6 @@ public Class<? extends ObjectType> getClassType() {
return classType;
}

public void setClassType(Class<? extends ObjectType> classType) {
this.classType = classType;
}

public enum IdentifierType {
OID,
FINAL
Expand All @@ -143,8 +147,4 @@ public IdentifierType getIdentifierType() {
return identifierType;
}

public void setIdentifierType(IdentifierType identifierType) {
this.identifierType = identifierType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,22 @@

package com.evolveum.midpoint.common.mining.utils;

import static com.evolveum.midpoint.common.mining.objects.analysis.RoleAnalysisAttributeDef.extractRealValue;

import java.util.*;
import javax.xml.namespace.QName;

import org.jetbrains.annotations.*;

import com.evolveum.midpoint.common.mining.objects.analysis.RoleAnalysisAttributeDef;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import org.jetbrains.annotations.UnmodifiableView;

import javax.xml.namespace.QName;
import java.util.*;

public class RoleAnalysisAttributeDefUtils {

public static final ItemName F_NAME = new ItemName(ObjectFactory.NAMESPACE, "name");
Expand Down Expand Up @@ -75,7 +73,7 @@ public ObjectQuery getQuery(String value) {
}

@Override
public String resolveSingleValueItem(PrismObject<?> prismObject, ItemPath itemPath) {
public String resolveSingleValueItem(@NotNull PrismObject<?> prismObject, @NotNull ItemPath itemPath) {
Item<PrismValue, ItemDefinition<?>> property = prismObject.findItem(itemPath);

if (property == null) {
Expand Down Expand Up @@ -244,7 +242,10 @@ public static RoleAnalysisAttributeDef getAttributeByDisplayValue(String display
}

@NotNull
private static RoleAnalysisAttributeDef getRoleAnalysisItemDefAssignment(ItemName itemName, String displayValue, QName targetType) {
private static RoleAnalysisAttributeDef getRoleAnalysisItemDefAssignment(
@NotNull ItemName itemName,
@NotNull String displayValue,
@NotNull QName targetType) {
return new RoleAnalysisAttributeDef(
ItemPath.create(itemName, AssignmentType.F_TARGET_REF),
true,
Expand Down Expand Up @@ -318,73 +319,201 @@ private static Set<String> resolveAssignment(
return resolvedValues;
}

@NotNull
private static Set<String> resolveRefs(
@NotNull PrismObject<?> prismObject,
@NotNull ItemPath itemPath) {
Set<String> resolvedValues = new HashSet<>();
Collection<Item<?, ?>> allItems = prismObject.getAllItems(itemPath);
for (Item<?, ?> item : allItems) {
Object realValue = item.getRealValue();
if (realValue instanceof ObjectReferenceType objectReference) {
resolvedValues.add(objectReference.getOid());
}
}

return resolvedValues;
}

private static @NotNull List<RoleAnalysisAttributeDef> loadRoleExtension() {

List<RoleAnalysisAttributeDef> attributes = new ArrayList<>();
PrismContainerDefinition<?> itemDefinitionByFullPath;

try {
itemDefinitionByFullPath = PrismContext.get().getSchemaRegistry().findItemDefinitionByFullPath(RoleType.class, PrismContainerDefinition.class, UserType.F_EXTENSION);
itemDefinitionByFullPath = PrismContext.get().getSchemaRegistry()
.findItemDefinitionByFullPath(UserType.class, PrismContainerDefinition.class, UserType.F_EXTENSION);
} catch (SchemaException e) {
throw new RuntimeException(e);
}

List<?> definitions = itemDefinitionByFullPath.getDefinitions();

for (Object definition : definitions) {
if (definition instanceof PrismPropertyDefinition<?> containerDefinition) {
//TODO resolve if string polyString targetRef complexObject etc...
Class<?> typeClass = containerDefinition.getTypeClass();
ItemPath itemName = containerDefinition.getItemName();

RoleAnalysisAttributeDef attribute = new RoleAnalysisAttributeDef(
ItemPath.create(RoleType.F_EXTENSION, itemName),
false, itemName + " extension", RoleType.class,
RoleAnalysisAttributeDef.IdentifierType.FINAL);
attributes.add(attribute);

if (definition instanceof PrismPropertyDefinition<?> prismPropertyDefinition) {
Class<?> typeClass = prismPropertyDefinition.getTypeClass();
boolean isSingleValue = prismPropertyDefinition.isSingleValue();

ItemPath itemName = prismPropertyDefinition.getItemName();
String attributeName = itemName + " extension";
RoleAnalysisAttributeDef attribute = createRoleAttribute(
prismPropertyDefinition, typeClass, isSingleValue, attributeName);
if (attribute != null) {
attributes.add(attribute);
}
}
}
return attributes;
}

private static @NotNull List<RoleAnalysisAttributeDef> loadUserExtension() {

List<RoleAnalysisAttributeDef> attributes = new ArrayList<>();
PrismContainerDefinition<?> itemDefinitionByFullPath;

try {
itemDefinitionByFullPath = PrismContext.get().getSchemaRegistry().findItemDefinitionByFullPath(UserType.class, PrismContainerDefinition.class, UserType.F_EXTENSION);
itemDefinitionByFullPath = PrismContext.get().getSchemaRegistry()
.findItemDefinitionByFullPath(UserType.class, PrismContainerDefinition.class, UserType.F_EXTENSION);
} catch (SchemaException e) {
throw new RuntimeException(e);
}

List<?> definitions = itemDefinitionByFullPath.getDefinitions();

for (Object definition : definitions) {
if (definition instanceof PrismPropertyDefinition<?> containerDefinition) {
//TODO resolve if string polyString targetRef complexObject etc...
ItemPath itemName = containerDefinition.getItemName();

RoleAnalysisAttributeDef attribute = new RoleAnalysisAttributeDef(
ItemPath.create(UserType.F_EXTENSION, itemName),
false,
itemName + " extension", UserType.class,
RoleAnalysisAttributeDef.IdentifierType.FINAL) {
@Override
public ObjectQuery getQuery(String value) {
return PrismContext.get().queryFor(UserType.class)
.item(getPath()).eq(value)
.build();
}
};
attributes.add(attribute);

if (definition instanceof PrismPropertyDefinition<?> prismPropertyDefinition) {
Class<?> typeClass = prismPropertyDefinition.getTypeClass();
boolean isSingleValue = prismPropertyDefinition.isSingleValue();

ItemPath itemName = prismPropertyDefinition.getItemName();
String attributeName = itemName + " extension";
RoleAnalysisAttributeDef attribute = createUserAttribute(
prismPropertyDefinition, typeClass, isSingleValue, attributeName);
if (attribute != null) {
attributes.add(attribute);
}
}
}

return attributes;
}

private static boolean isPolyStringOrString(@NotNull ItemDefinition<?> def) {
return def.getTypeName().getLocalPart().equals(PolyStringType.COMPLEX_TYPE.getLocalPart())
|| def.getTypeName().getLocalPart().equals("string")
|| def.getTypeName().getLocalPart().equals("PolyString");
private static @Nullable RoleAnalysisAttributeDef createUserAttribute(
@NotNull PrismPropertyDefinition<?> prismPropertyDefinition,
@NotNull Class<?> typeClass,
boolean isSingleValue,
@NotNull String attributeName) {
if (typeClass.equals(Integer.class)
|| typeClass.equals(Long.class)
|| typeClass.equals(Boolean.class)
|| typeClass.equals(Double.class)
|| typeClass.equals(String.class)
|| typeClass.equals(PolyString.class)) {

return new RoleAnalysisAttributeDef(
ItemPath.create(UserType.F_EXTENSION, prismPropertyDefinition.getItemName()),
isSingleValue,
attributeName,
UserType.class,
RoleAnalysisAttributeDef.IdentifierType.FINAL) {

@Override
public ObjectQuery getQuery(String value) {
return PrismContext.get().queryFor(UserType.class)
.item(getPath()).eq(value)
.build();
}
};
} else if (typeClass.equals(ObjectReferenceType.class)) {
return new RoleAnalysisAttributeDef(
ItemPath.create(UserType.F_EXTENSION, prismPropertyDefinition.getItemName()),
isSingleValue,
attributeName,
UserType.class,
RoleAnalysisAttributeDef.IdentifierType.OID) {
@Override
public ObjectQuery getQuery(String value) {
return PrismContext.get().queryFor(UserType.class)
.item(getPath()).ref(value)
.build();
}

@Override
public String resolveSingleValueItem(@NotNull PrismObject<?> prismObject, @NotNull ItemPath itemPath) {
return resolveRef(prismObject, itemPath);
}

@Override
public @NotNull Set<String> resolveMultiValueItem(@NotNull PrismObject<?> prismObject, @NotNull ItemPath itemPath) {
return resolveRefs(prismObject, itemPath);
}
};
}
return null;
}

private static @Nullable RoleAnalysisAttributeDef createRoleAttribute(
@NotNull PrismPropertyDefinition<?> prismPropertyDefinition,
@NotNull Class<?> typeClass,
boolean isSingleValue,
@NotNull String attributeName) {
if (typeClass.equals(Integer.class)
|| typeClass.equals(Long.class)
|| typeClass.equals(Boolean.class)
|| typeClass.equals(Double.class)
|| typeClass.equals(String.class)
|| typeClass.equals(PolyString.class)) {

return new RoleAnalysisAttributeDef(
ItemPath.create(RoleType.F_EXTENSION, prismPropertyDefinition.getItemName()),
isSingleValue,
attributeName,
RoleType.class,
RoleAnalysisAttributeDef.IdentifierType.FINAL) {
@Override
public ObjectQuery getQuery(String value) {
return PrismContext.get().queryFor(RoleType.class)
.item(getPath()).eq(value)
.build();
}
};
} else if (typeClass.equals(ObjectReferenceType.class)) {
return new RoleAnalysisAttributeDef(
ItemPath.create(RoleType.F_EXTENSION, prismPropertyDefinition.getItemName()),
isSingleValue,
attributeName,
RoleType.class,
RoleAnalysisAttributeDef.IdentifierType.OID) {
@Override
public ObjectQuery getQuery(String value) {
return PrismContext.get().queryFor(RoleType.class)
.item(getPath()).ref(value)
.build();
}

@Override
public String resolveSingleValueItem(@NotNull PrismObject<?> prismObject, @NotNull ItemPath itemPath) {
return resolveRef(prismObject, itemPath);
}

@Override
public @NotNull Set<String> resolveMultiValueItem(@NotNull PrismObject<?> prismObject, @NotNull ItemPath itemPath) {
return resolveRefs(prismObject, itemPath);
}
};
}
return null;
}

@Nullable
private static String resolveRef(PrismObject<?> prismObject, ItemPath itemPath) {
Item<PrismValue, ItemDefinition<?>> property = prismObject.findItem(itemPath);
if (property != null) {
Object object = property.getRealValue();
if (object instanceof ObjectReferenceType objectReference) {
return objectReference.getOid();
}
return extractRealValue(object);
}
return null;
}
}

0 comments on commit 27d3161

Please sign in to comment.