Skip to content

Commit

Permalink
repo-sqale: extension type checking refactored, sqale tests were fixed
Browse files Browse the repository at this point in the history
Tests now conform to strict real value type checking (e.g. xsd:integer
uses BigInteger values, not Integer).
Supported type info in ExtUtils is better encapsulated (still static).
  • Loading branch information
virgo47 committed Aug 25, 2021
1 parent 32f32c5 commit 669dfc8
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
import java.math.BigInteger;
import java.time.temporal.ChronoUnit;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;

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

import com.evolveum.midpoint.prism.PrismPropertyDefinition;
import com.evolveum.midpoint.prism.polystring.PolyString;
Expand All @@ -26,7 +25,6 @@
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import com.google.common.collect.ImmutableMap;

/**
* Utilities and constants related to extension item processing, especially as JSONB.
Expand All @@ -36,44 +34,42 @@ public class ExtUtils {
/**
* Supported types for extension properties - without references and enums treated differently.
*/
public static final Set<QName> SUPPORTED_INDEXED_EXTENSION_TYPES = Set.of(
DOMUtil.XSD_BOOLEAN,
DOMUtil.XSD_INT,
DOMUtil.XSD_LONG,
DOMUtil.XSD_SHORT,
DOMUtil.XSD_INTEGER,
DOMUtil.XSD_DECIMAL,
DOMUtil.XSD_STRING,
DOMUtil.XSD_DOUBLE,
DOMUtil.XSD_FLOAT,
DOMUtil.XSD_DATETIME,
PolyStringType.COMPLEX_TYPE);

public static final Map<String,QName> SUPPORTED_TYPE_URI_TO_QNAME;
public static final Map<String, Class<?>> SUPPORTED_TYPE_URI_TO_REAL_CLASS = ImmutableMap.<String,Class<?>>builder()
.put(QNameUtil.qNameToUri(DOMUtil.XSD_INT), Integer.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_LONG), Long.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_SHORT), Short.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_DECIMAL), BigDecimal.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_INTEGER), BigInteger.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_STRING), String.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_FLOAT), Float.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_DOUBLE), Double.class)
.put(QNameUtil.qNameToUri(DOMUtil.XSD_DATETIME), XMLGregorianCalendar.class)
.put(QNameUtil.qNameToUri(PolyStringType.COMPLEX_TYPE), PolyString.class)

.build();
private static final Map<String, SupportedExtensionTypeInfo> SUPPORTED_INDEXED_EXTENSION_TYPES = new HashMap<>();

static {
HashMap<String, QName> uriMap = new HashMap<>();
for (QName name : SUPPORTED_INDEXED_EXTENSION_TYPES) {
uriMap.put(QNameUtil.qNameToUri(name), name);
addType(DOMUtil.XSD_BOOLEAN, Boolean.class);
addType(DOMUtil.XSD_INT, Integer.class);
addType(DOMUtil.XSD_LONG, Long.class);
addType(DOMUtil.XSD_SHORT, Short.class);
addType(DOMUtil.XSD_INTEGER, BigInteger.class);
addType(DOMUtil.XSD_DECIMAL, BigDecimal.class);
addType(DOMUtil.XSD_STRING, String.class);
addType(DOMUtil.XSD_FLOAT, Float.class);
addType(DOMUtil.XSD_DOUBLE, Double.class);
addType(DOMUtil.XSD_DATETIME, XMLGregorianCalendar.class);
addType(PolyStringType.COMPLEX_TYPE, PolyString.class);
}

}
private static void addType(QName typeName, Class<?> valueClass) {
String uri = QNameUtil.qNameToUri(typeName);
SUPPORTED_INDEXED_EXTENSION_TYPES.put(uri,
new SupportedExtensionTypeInfo(uri, typeName, valueClass));
}

/**
* Returns expected class for real values for registered types, or `null`.
*/
public static @Nullable Class<?> getRealValueClass(String typeUri) {
SupportedExtensionTypeInfo info = SUPPORTED_INDEXED_EXTENSION_TYPES.get(typeUri);
return info != null ? info.realValueClass : null;
}

public static boolean isRegisteredType(QName typeName) {
return SUPPORTED_INDEXED_EXTENSION_TYPES.containsKey(QNameUtil.qNameToUri(typeName));
}

SUPPORTED_TYPE_URI_TO_QNAME = Collections.unmodifiableMap(uriMap);
public static QName getSupportedTypeName(String typeUri) {
return SUPPORTED_INDEXED_EXTENSION_TYPES.get(typeUri).typeName;
}

public static boolean isEnumDefinition(PrismPropertyDefinition<?> definition) {
Expand All @@ -87,4 +83,16 @@ public static String extensionDateTime(@NotNull XMLGregorianCalendar dateTime) {
.truncatedTo(ChronoUnit.MILLIS)
.toString();
}

public static class SupportedExtensionTypeInfo {
public final String uri; // see QNameUtil.qNameToUri()
public final QName typeName;
public final Class<?> realValueClass;

public SupportedExtensionTypeInfo(String uri, QName typeName, Class<?> realValueClass) {
this.uri = uri;
this.typeName = typeName;
this.realValueClass = realValueClass;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,14 @@ private Object convertExtItemValue(Object realValue, ExtItemInfo extItemInfo) {
}

throw new IllegalArgumentException(
"Unsupported type '" + realValue.getClass() + "' for value '" + realValue + "'.");
"Unsupported type '" + realValue.getClass().getName() + "' for value '" + realValue + "'.");
}

private void checkRealValueType(Object realValue, MExtItem extItemInfo) {
Class<?> realValueType = ExtUtils.SUPPORTED_TYPE_URI_TO_REAL_CLASS.get(extItemInfo.valueType);
if (realValueType != null && !realValueType.isAssignableFrom(realValue.getClass()) ) {
throw new IllegalArgumentException("Incorrect real value type "
+ realValue.getClass() + " for item " + extItemInfo.itemName);
Class<?> realValueType = ExtUtils.getRealValueClass(extItemInfo.valueType);
if (realValueType != null && !realValueType.isAssignableFrom(realValue.getClass())) {
throw new IllegalArgumentException("Incorrect real value type '"
+ realValue.getClass().getName() + "' for item " + extItemInfo.itemName);
}
}

Expand All @@ -159,7 +159,7 @@ public MExtItem resolveExtensionItem(
return null;
}
// enum is recognized by having allowed values
if (!ExtUtils.SUPPORTED_INDEXED_EXTENSION_TYPES.contains(definition.getTypeName())
if (!ExtUtils.isRegisteredType(definition.getTypeName())
&& !ExtUtils.isEnumDefinition(((PrismPropertyDefinition<?>) definition))) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
package com.evolveum.midpoint.repo.sqale.qmodel.ext;

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

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.path.ItemName;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;

/**
* Querydsl "row bean" type related to {@link QExtItem}.
Expand All @@ -21,7 +23,12 @@ public class MExtItem {

public Integer id;
public String itemName;
public String valueType; // references use ObjectReferenceType#COMPLEX_TYPE

/**
* Value type as URI produced by {@link QNameUtil#qNameToUri(QName)}.
* References use URI for {@link ObjectReferenceType#COMPLEX_TYPE} (midPoint, not Prism one).
*/
public String valueType;
public MExtItemHolderType holderType;
public MExtItemCardinality cardinality;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private void applyShadowAttributesDefinitions(ShadowType shadowType) throws Sche
}

private ItemDefinition<?> definitionFrom(QName name, MExtItem itemInfo) {
QName typeName = ExtUtils.SUPPORTED_TYPE_URI_TO_QNAME.get(itemInfo.valueType);
QName typeName = ExtUtils.getSupportedTypeName(itemInfo.valueType);
final MutableItemDefinition<?> def;
if (ObjectReferenceType.COMPLEX_TYPE.equals(typeName)) {
def = PrismContext.get().definitionFactory().createReferenceDefinition(name, typeName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ public void test305AddObjectWithExtensionItemsOfVariousSimpleTypes()
addExtensionValue(extensionContainer, "int", 1);
addExtensionValue(extensionContainer, "short", (short) 2);
addExtensionValue(extensionContainer, "long", 3L);
addExtensionValue(extensionContainer, "integer", 4);
addExtensionValue(extensionContainer, "integer", BigInteger.valueOf(4));
addExtensionValue(extensionContainer, "decimal",
new BigDecimal("12345678901234567890.12345678901234567890"));
addExtensionValue(extensionContainer, "decimal-2", new BigDecimal("12345678901234567890"));
Expand Down Expand Up @@ -742,7 +742,7 @@ public void test305AddObjectWithExtensionItemsOfVariousSimpleTypes()
.containsEntry(extensionKey(extensionContainer, "int"), 1)
.containsEntry(extensionKey(extensionContainer, "short"), 2) // returned as Integer
.containsEntry(extensionKey(extensionContainer, "long"), 3) // returned as Integer
.containsEntry(extensionKey(extensionContainer, "integer"), 4)
.containsEntry(extensionKey(extensionContainer, "integer"), 4) // returned as Integer
.containsEntry(extensionKey(extensionContainer, "decimal"),
new BigDecimal("12345678901234567890.12345678901234567890"))
.containsEntry(extensionKey(extensionContainer, "decimal-2"),
Expand Down Expand Up @@ -868,7 +868,7 @@ public void test310AddObjectWithAssignmentExtensions()
.assignment(assignment);
ExtensionType extensionContainer = assignment.getExtension();
addExtensionValue(extensionContainer, "string-mv", "string-value1", "string-value2");
addExtensionValue(extensionContainer, "integer", 1);
addExtensionValue(extensionContainer, "integer", BigInteger.valueOf(1));
String targetOid = UUID.randomUUID().toString();
addExtensionValue(extensionContainer, "ref", ref(targetOid, UserType.COMPLEX_TYPE));

Expand All @@ -885,7 +885,7 @@ public void test310AddObjectWithAssignmentExtensions()
assertThat(Jsonb.toMap(row.ext))
.containsEntry(extensionKey(extensionContainer, "string-mv"),
List.of("string-value1", "string-value2"))
.containsEntry(extensionKey(extensionContainer, "integer"), 1)
.containsEntry(extensionKey(extensionContainer, "integer"), 1) // returned as Integer
.containsEntry(extensionKey(extensionContainer, "ref"),
Map.of("o", targetOid,
"t", MObjectType.USER.name(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public void initObjects() throws Exception {
addExtensionValue(user1Extension, "string", "string-value");
addExtensionValue(user1Extension, "int", 1);
addExtensionValue(user1Extension, "long", 2L);
addExtensionValue(user1Extension, "short", 3);
addExtensionValue(user1Extension, "short", (short) 3);
addExtensionValue(user1Extension, "decimal",
new BigDecimal("12345678901234567890.12345678901234567890"));
addExtensionValue(user1Extension, "double", Double.MAX_VALUE);
Expand All @@ -218,7 +218,7 @@ public void initObjects() throws Exception {
user1.assignment(new AssignmentType(prismContext)
.lifecycleState("assignment1-3-ext")
.extension(user1AssignmentExtension));
addExtensionValue(user1AssignmentExtension, "integer", 47);
addExtensionValue(user1AssignmentExtension, "integer", BigInteger.valueOf(47));
user1Oid = repositoryService.addObject(user1.asPrismObject(), null, result);

UserType user2 = new UserType(prismContext).name("user-2")
Expand All @@ -237,7 +237,7 @@ public void initObjects() throws Exception {
asXMLGregorianCalendar(Instant.ofEpochMilli(1633_100_000_000L)));
addExtensionValue(user2Extension, "int", 2);
addExtensionValue(user2Extension, "double", Double.MIN_VALUE); // positive, close to zero
addExtensionValue(user2Extension, "float", 0);
addExtensionValue(user2Extension, "float", 0f);
addExtensionValue(user2Extension, "ref", ref(orgXOid, OrgType.COMPLEX_TYPE));
addExtensionValue(user2Extension, "string-mv", "string-value2", "string-value3");
addExtensionValue(user2Extension, "poly", PolyString.fromOrig("poly-value-user2"));
Expand Down

0 comments on commit 669dfc8

Please sign in to comment.