diff --git a/.travis.yml b/.travis.yml index a743e1fc463..e9125a14380 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,4 @@ -sudo: false +sudo: required dist: trusty language: java @@ -15,20 +15,19 @@ before_install: - unzip -qq apache-maven-3.3.9-bin.zip - export M2_HOME=$PWD/apache-maven-3.3.9 - export PATH=$M2_HOME/bin:$PATH - - export MAVEN_OPTS='-Xmx2g -XX:MaxPermSize=256m' + - export MAVEN_OPTS='-Xmx2g' # custom script is used so build and tests are done in one mvn command, separating it (as Travis does by default) leads to problem with ConnId (notably DummyResource) script: mvn clean install addons: hostname: localhost # workaround for short hostname - apt: - packages: - - oracle-java8-installer # install newest JDK8 - #- openjdk-8-jdk + #apt: + #packages: + #- oracle-java8-installer # install newest JDK8 jdk: - - openjdk7 - - oraclejdk7 - #- openjdk8 + #- openjdk7 + #- oraclejdk7 - oraclejdk8 + - openjdk8 diff --git a/infra/common/src/test/java/com/evolveum/midpoint/common/refinery/TestRefinedSchema.java b/infra/common/src/test/java/com/evolveum/midpoint/common/refinery/TestRefinedSchema.java index 2d1def12a37..ab90896912e 100644 --- a/infra/common/src/test/java/com/evolveum/midpoint/common/refinery/TestRefinedSchema.java +++ b/infra/common/src/test/java/com/evolveum/midpoint/common/refinery/TestRefinedSchema.java @@ -158,11 +158,11 @@ private void assertRefinedSchema(ResourceType resourceType, RefinedResourceSchem RefinedObjectClassDefinition rAccountDef = rSchema.getRefinedDefinition(ShadowKindType.ACCOUNT, (String)null); RefinedObjectClassDefinition accountDefByNullObjectclass = rSchema.findRefinedDefinitionByObjectClassQName(ShadowKindType.ACCOUNT, null); - assertTrue("findAccountDefinitionByObjectClass(null) returned wrong value", rAccountDef.equals(accountDefByNullObjectclass)); + assertEquals("findAccountDefinitionByObjectClass(null) returned wrong value", rAccountDef, accountDefByNullObjectclass); RefinedObjectClassDefinition accountDefByIcfAccountObjectclass = rSchema.findRefinedDefinitionByObjectClassQName(ShadowKindType.ACCOUNT, new QName(resourceType.getNamespace(), SchemaTestConstants.ICF_ACCOUNT_OBJECT_CLASS_LOCAL_NAME)); - assertTrue("findAccountDefinitionByObjectClass(ICF account) returned wrong value", rAccountDef.equals(accountDefByIcfAccountObjectclass)); + assertEquals("findAccountDefinitionByObjectClass(ICF account) returned wrong value", rAccountDef, accountDefByIcfAccountObjectclass); assertRObjectClassDef(rAccountDef, resourceType, sourceLayer, validationLayer); System.out.println("Refined account definitionn:"); @@ -341,7 +341,7 @@ private void assertAccountShadow(PrismObject accObject, PrismObject< PrismAsserts.assertPropertyValue(accObject, ShadowType.F_INTENT, SchemaConstants.INTENT_DEFAULT); PrismContainer attributes = accObject.findOrCreateContainer(SchemaConstants.C_ATTRIBUTES); - assertEquals("Wrong type of definition in account", ResourceAttributeContainerDefinition.class, attributes.getDefinition().getClass()); + assertEquals("Wrong type of definition in account", ResourceAttributeContainerDefinitionImpl.class, attributes.getDefinition().getClass()); ResourceAttributeContainerDefinition attrDef = (ResourceAttributeContainerDefinition)attributes.getDefinition(); assertAttributeDefs(attrDef, resourceType, null, LayerType.MODEL); @@ -435,7 +435,7 @@ private void assertAttributeDefs(ResourceAttributeContainerDefinition attrsDef, assertNotNull("Null account definition", attrsDef); assertEquals(SchemaConstants.INTENT_DEFAULT, attrsDef.getIntent()); assertEquals("AccountObjectClass", attrsDef.getComplexTypeDefinition().getTypeName().getLocalPart()); - assertEquals("Wrong objectclass in the definition of definition in account", RefinedObjectClassDefinition.class, attrsDef.getComplexTypeDefinition().getClass()); + assertEquals("Wrong objectclass in the definition of definition in account", RefinedObjectClassDefinitionImpl.class, attrsDef.getComplexTypeDefinition().getClass()); RefinedObjectClassDefinition rAccount = (RefinedObjectClassDefinition) attrsDef.getComplexTypeDefinition(); assertRObjectClassDef(rAccount, resourceType, sourceLayer, validationLayer); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java index 538220a41ef..cd2d703e690 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/Item.java @@ -393,6 +393,9 @@ public boolean add(V newValue) throws SchemaException { public boolean add(V newValue, boolean checkUniqueness) throws SchemaException { checkMutability(); + if (newValue.getPrismContext() == null) { + newValue.setPrismContext(prismContext); + } newValue.setParent(this); if (checkUniqueness && containsEquivalentValue(newValue)) { return false; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/ItemDefinition.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/ItemDefinition.java index b94c322071f..b6ded60425f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/ItemDefinition.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/ItemDefinition.java @@ -95,4 +95,5 @@ public interface ItemDefinition extends Definition { @Override void revive(PrismContext prismContext); + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java index 6f0dab101d1..d5f4a966bed 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismContainerValue.java @@ -61,8 +61,6 @@ public class PrismContainerValue extends PrismValue imp // It can be lazily evaluated based on containerable value. private ComplexTypeDefinition complexTypeDefinition = null; - transient private PrismContext prismContext; - public PrismContainerValue() { } @@ -79,15 +77,10 @@ public PrismContainerValue(C containerable, PrismContext prismContext) { this.prismContext = prismContext; } - private void setPrismContext(PrismContext prismContext) { - this.prismContext = prismContext; - } - public PrismContainerValue(OriginType type, Objectable source, PrismContainerable container, Long id, ComplexTypeDefinition complexTypeDefinition, PrismContext prismContext) { - super(type, source, container); + super(prismContext, type, source, container); this.id = id; this.complexTypeDefinition = complexTypeDefinition; - this.prismContext = prismContext; } @Override @@ -1447,4 +1440,11 @@ public Class getRealClass() { } return resolveClass(null); } + + @SuppressWarnings("unchecked") + @Nullable + @Override + public T getRealValue() { + return (T) asContainerable(); + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParser.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParser.java index 68f837ae72d..93792d7d4ea 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParser.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParser.java @@ -17,17 +17,13 @@ package com.evolveum.midpoint.prism; import com.evolveum.midpoint.prism.xnode.RootXNode; -import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.util.exception.SchemaException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.w3c.dom.Element; import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; -import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.util.List; /** @@ -37,17 +33,18 @@ * 1. how to determine the type of data to be retrieved, * 2. how to determine the name of the item that is to be created (in case of prism items). * - * For most cases, this data can be determined from the input. E.g. if we are parsing a prism object that is rooted at the + * For most cases, both can be determined from the input. E.g. if we are parsing a prism object that is rooted at the * "user" XML element, it is clear that the type is c:UserType and the name is c:user. In other cases, the algorithms * are the following: * * Data type determination: We collect all the available data, i.e. - * - source data (xsi:type/@type), - * - itemDefinition, - * - itemName, - * - typeName, - * - typeClass - * and take the most specific of these. + * - explicit type specification in source data (xsi:type/@type), + * - itemDefinition provided by the caller, + * - item name in source data, + * - itemName provided by the caller, + * - typeName provided by the caller, + * - typeClass provided by the caller + * and take the most specific of these. In case of conflict we report an error. * * Data name determination: First name that is present takes precedence: * 1. itemName @@ -92,8 +89,8 @@ public interface PrismParser { PrismParser yaml(); /** - * Provides a parsing context for the parser. The context contains e.g. mode of operations (set by client) - * or a list of warnings (maintained by the parser). + * Provides a parsing context for the parser. The context contains e.g. selection of strict/compat + * mode of operation (set by client) or a list of warnings (maintained by the parser). * @param context The parsing context. * @return Updated parser. */ @@ -123,14 +120,6 @@ public interface PrismParser { @NotNull PrismParser definition(ItemDefinition itemDefinition); - /** - * Tells parser what name to use for parsed item. Optional. - * @param itemName Item name to use. - * @return Updated parser. - */ - @NotNull - PrismParser name(QName itemName); - /** * Tells parser what data type to expect. Optional. * @param typeName Data type to expect. @@ -147,6 +136,14 @@ public interface PrismParser { @NotNull PrismParser type(Class typeClass); + /** + * Tells parser what name to use for parsed item. Optional. + * @param itemName Item name to use. + * @return Updated parser. + */ + @NotNull + PrismParser name(QName itemName); + /** * Parses the input as a prism object. * @return The object. @@ -156,26 +153,28 @@ public interface PrismParser { /** * Parses the input as a prism item. (Object, container, reference, value.) + * May return raw property values as part of the prism structure, if definitions are not known. * @return The item. */ Item parseItem() throws SchemaException, IOException; /** * Parses the input as a prism value. (Container value, reference value, property value.) + * May return raw property values as part of the prism structure, if definitions are not known. * @return The item. */ IV parseItemValue() throws SchemaException, IOException; /** * Parses a real value - either property or container value. - * @param clazz Expected class of the data (can be Object.class when unknown). - * @return Real value - POJO, Containerable or Objectable. + * @param clazz Expected class of the data. May be null if unknown. + * @return Real value - POJO, Containerable, Objectable or Referencable. */ - T parseRealValue(Class clazz) throws IOException, SchemaException; + T parseRealValue(@Nullable Class clazz) throws IOException, SchemaException; /** - * Parses a real value with an unknown class. - * @return Real value - POJO, Containerable or Objectable. + * Parses a real value. The class is not supplied by the caller, so it has to be determined from the data source. + * @return Real value - POJO, Containerable, Objectable or Referencable. */ T parseRealValue() throws IOException, SchemaException; @@ -185,11 +184,29 @@ public interface PrismParser { JAXBElement parseRealValueToJaxbElement() throws IOException, SchemaException; /** - * Parses the input into RootXNode. + * Parses the input into RootXNode. This is a bit unusual approach, skipping the unmarshalling phase altogether. + * But it is useful at some places. * @return RootXNode corresponding to the input. */ RootXNode parseToXNode() throws IOException, SchemaException; + /** + * Parses either an item, or a real value. It depends on the type declaration or item name in the source data. + * 1) If explicit type is present, it is taken into account. If it corresponds to a prism item, the input is parsed + * as a prism item. Otherwise, it is parsed as a real value (containerable or simple POJO), if possible. + * 2) If there is no type, the item name is consulted. If it corresponds to a prism item, the input is parsed + * as a prism item. Otherwise, an exception is thrown. + * + * Pre-set parameters (itemDefinition, typeName, itemName) must NOT be present. + * + * Use with utmost care. If at all possible, avoid it. + * + * @return either prism item (Item) or a real value (Object) + */ + Object parseItemOrRealValue() throws IOException, SchemaException; + + + // ============= other methods (convenience ones, deprecated ones etc) ============= /** @@ -214,18 +231,4 @@ public interface PrismParser { // T parseAtomicValue(QName typeName) throws IOException, SchemaException; - /** - * Parses (almost) anything: either an item with a definition, or an atomic (i.e. property-like) value. - * Does not care for schemaless items! - * - * CAUTION: EXPERIMENTAL - Avoid using this method if at all possible. - * Its result is not well defined, namely, whether it returns Item or a value. - * - * Used for scripting and wf-related data serialization. To be replaced. - * - * @return either Item or an unmarshalled bean value - */ - @Deprecated - Object parseAnyData() throws IOException, SchemaException; - } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParserNoIO.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParserNoIO.java index c8fe23f9544..7b5b895c60c 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParserNoIO.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismParserNoIO.java @@ -66,11 +66,10 @@ public interface PrismParserNoIO extends PrismParser { T parseRealValue() throws SchemaException; JAXBElement parseRealValueToJaxbElement() throws SchemaException; RootXNode parseToXNode() throws SchemaException; + Object parseItemOrRealValue() throws SchemaException; - // auxiliary and deprecated methods + // auxiliary methods @NotNull List> parseObjects() throws SchemaException; - @Deprecated - Object parseAnyData() throws SchemaException; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java index 7f6d24846c4..da4b65acfaa 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinition.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.DisplayableValue; import com.evolveum.midpoint.util.exception.SchemaException; @@ -32,10 +33,27 @@ public interface PrismPropertyDefinition extends ItemDefinition + * The returned type is either XSD simple type or complex type. It may not + * be defined in the same schema (especially if it is standard XSD simple + * type). + * + * @return QName of the property value type + * + * NOTE: This is very strange property. Isn't it the same as typeName(). + * It is even not used in midPoint. Marking as deprecated. + */ + @Deprecated QName getValueType(); Boolean isIndexed(); + default boolean isAnyType() { + return DOMUtil.XSD_ANYTYPE.equals(getTypeName()); + } + QName getMatchingRuleQName(); @Override diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinitionImpl.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinitionImpl.java index 9d9996f4f89..322f8dab741 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinitionImpl.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyDefinitionImpl.java @@ -86,25 +86,13 @@ public Collection> getAllowedValues() { public T defaultValue(){ return defaultValue; } - /** - * Returns QName of the property value type. - *

- * The returned type is either XSD simple type or complex type. It may not - * be defined in the same schema (especially if it is standard XSD simple - * type). - * - * @return QName of the property value type - */ + @Override public QName getValueType() { return valueType; } - void setValueType(QName valueType) { - this.valueType = valueType; - } - - /** + /** * This is XSD annotation that specifies whether a property should * be indexed in the storage. It can only apply to properties. It * has following meaning: diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyValue.java index 61f47d766e5..a76f845a7a2 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismPropertyValue.java @@ -46,6 +46,7 @@ import java.util.Comparator; import org.apache.commons.lang.StringUtils; +import org.jetbrains.annotations.Nullable; import org.jvnet.jaxb2_commons.lang.Equals; import org.w3c.dom.Element; @@ -68,8 +69,16 @@ public PrismPropertyValue(T value) { this(value, null, null); } + public PrismPropertyValue(T value, PrismContext prismContext) { + this(value, prismContext, null, null); + } + public PrismPropertyValue(T value, OriginType type, Objectable source) { - super(type,source); + this(value, null, type, source); + } + + public PrismPropertyValue(T value, PrismContext prismContext, OriginType type, Objectable source) { + super(type, source); if (value instanceof PrismPropertyValue) { throw new IllegalArgumentException("Probably problem somewhere, encapsulating property " + "value object to another property value."); @@ -112,13 +121,10 @@ public T getValue() { // We are weak now. If there is no better definition for this we assume a default definition and process // the attribute now. But we should rather do this: TODO: // throw new IllegalStateException("Attempt to get value withot a type from raw value of property "+getParent()); - if (parent != null && parent.getPrismContext() != null) { - def = SchemaRegistryImpl.createDefaultItemDefinition(parent.getElementName(), parent.getPrismContext()); + if (parent != null && getPrismContext() != null) { + def = SchemaRegistryImpl.createDefaultItemDefinition(parent.getElementName(), getPrismContext()); } else if (PrismContextImpl.isAllowSchemalessSerialization()) { - if (rawElement instanceof Element) { - // Do the most stupid thing possible. Assume string value. And there will be no definition. - value = (T) ((Element)rawElement).getTextContent(); - } else if (rawElement instanceof PrimitiveXNode) { + if (rawElement instanceof PrimitiveXNode) { try { QName type = rawElement.getTypeQName() != null ? rawElement.getTypeQName() : DOMUtil.XSD_STRING; value = (T) ((PrimitiveXNode) rawElement).getParsedValueWithoutRecording(type); @@ -140,6 +146,9 @@ public T getValue() { throw new IllegalStateException(e.getMessage(),e); } } + if (rawElement != null) { + return (T) RawType.create(rawElement, getPrismContext()); + } } return value; } @@ -167,8 +176,9 @@ public boolean isRaw() { @Override public void applyDefinition(ItemDefinition definition) throws SchemaException { - if (definition != null && rawElement !=null) { - value = (T) parseRawElementToNewRealValue(this, (PrismPropertyDefinition) definition); + PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) definition; + if (propertyDefinition != null && !propertyDefinition.isAnyType() && rawElement != null) { + value = (T) parseRawElementToNewRealValue(this, propertyDefinition); rawElement = null; } } @@ -647,4 +657,10 @@ public JAXBElement toJaxbElement() { public Class getRealClass() { return value != null ? value.getClass() : null; } + + @Nullable + @Override + public T getRealValue() { + return (T) getValue(); + } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java index 18fa902e6de..5d6dff328a7 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismReferenceValue.java @@ -35,6 +35,7 @@ import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; import com.evolveum.prism.xml.ns._public.types_3.EvaluationTimeType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import org.jetbrains.annotations.Nullable; /** * @author Radovan Semancik @@ -500,21 +501,37 @@ public String toString() { } public Referencable asReferencable() { - if (referencable == null){ - Itemable parent = getParent(); + if (referencable != null) { + return referencable; + } + + Itemable parent = getParent(); + if (parent != null) { QName xsdType = parent.getDefinition().getTypeName(); Class clazz = getPrismContext().getSchemaRegistry().getCompileTimeClass(xsdType); - if (clazz != null){ + if (clazz != null) { try { referencable = (Referencable) clazz.newInstance(); } catch (InstantiationException | IllegalAccessException e) { - throw new SystemException("Couldn't create jaxb object instance of '" + clazz + "': "+e.getMessage(), e); + throw new SystemException("Couldn't create jaxb object instance of '" + clazz + "': " + e.getMessage(), + e); } } referencable.setupReferenceValue(this); } - return referencable; - + + // A hack, just to avoid crashes. + return new Referencable() { + PrismReferenceValue referenceValue = PrismReferenceValue.this; + @Override + public PrismReferenceValue asReferenceValue() { + return referenceValue; + } + @Override + public void setupReferenceValue(PrismReferenceValue value) { + referenceValue = value; + } + }; } @Override @@ -592,6 +609,13 @@ public String toHumanReadableString() { @Override public Class getRealClass() { - return PrismReferenceValue.class; + return Referencable.class; + } + + @SuppressWarnings("unchecked") + @Nullable + @Override + public Referencable getRealValue() { + return asReferencable(); } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismValue.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismValue.java index 4c822b874e7..66cf9c4c561 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismValue.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismValue.java @@ -45,27 +45,39 @@ public abstract class PrismValue implements IPrismValue { private OriginType originType; private Objectable originObject; private Itemable parent; - protected Element domElement = null; private transient Map userData = new HashMap<>(); protected boolean immutable; - PrismValue() { - super(); + transient protected PrismContext prismContext; + + PrismValue() { + } + + PrismValue(PrismContext prismContext) { + this.prismContext = prismContext; } PrismValue(OriginType type, Objectable source) { - super(); + this(null, type, source); + } + + PrismValue(PrismContext prismContext, OriginType type, Objectable source) { + this.prismContext = prismContext; this.originType = type; this.originObject = source; } - PrismValue(OriginType type, Objectable source, Itemable parent) { - super(); + PrismValue(PrismContext prismContext, OriginType type, Objectable source, Itemable parent) { + this.prismContext = prismContext; this.originType = type; this.originObject = source; this.parent = parent; } + public void setPrismContext(PrismContext prismContext) { + this.prismContext = prismContext; + } + public void setOriginObject(Objectable source) { this.originObject = source; } @@ -142,8 +154,12 @@ public static void clearParent(List> values) { @Override public PrismContext getPrismContext() { + if (prismContext != null) { + return prismContext; + } if (parent != null) { - return parent.getPrismContext(); + prismContext = parent.getPrismContext(); + return prismContext; } return null; } @@ -169,6 +185,9 @@ public void applyDefinition(ItemDefinition definition, boolean force) throws Sch } public void revive(PrismContext prismContext) throws SchemaException { + if (this.prismContext == null) { + this.prismContext = prismContext; + } recompute(prismContext); } @@ -418,4 +437,7 @@ protected void checkMutability() { @Nullable abstract public Class getRealClass(); + @Nullable + abstract public T getRealValue(); + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/JsonLexicalProcessor.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/JsonLexicalProcessor.java index 961047aa499..7510f53c96f 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/JsonLexicalProcessor.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/lex/json/JsonLexicalProcessor.java @@ -114,7 +114,7 @@ protected void serializeFromPrimitive(PrimitiveXNode primitive, AbstractJ if (explicitType != null) { ctx.generator.writeStartObject(); ctx.generator.writeStringField(PROP_TYPE, QNameUtil.qNameToUri(primitive.getTypeQName())); - ctx.generator.writeObjectField(PROP_VALUE, primitive.getValue()); + ctx.generator.writeObjectField(PROP_VALUE, primitive.getStringValue()); ctx.generator.writeEndObject(); } else { serializePrimitiveTypeLessValue(primitive, ctx); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImpl.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImpl.java index d5d4451030d..d0559eaf14c 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImpl.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImpl.java @@ -19,7 +19,6 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.lex.LexicalProcessor; import com.evolveum.midpoint.prism.xnode.RootXNode; -import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.util.exception.SchemaException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -146,6 +145,7 @@ Item doParseItem() th return doParseItem(xnode); } + @SuppressWarnings("unchecked") private Item doParseItem(RootXNode xnode) throws IOException, SchemaException { return (Item) prismContext.getPrismUnmarshaller().parseItem(xnode, itemDefinition, itemName, typeName, typeClass, context); } @@ -188,30 +188,24 @@ private T doParseRealValue(Class clazz, RootXNode root) throws IOExceptio if (clazz == null && info.getTypeName() != null) { clazz = (Class) prismContext.getSchemaRegistry().determineClassForType(info.getTypeName()); } -// if (clazz == null) { -// throw new IllegalArgumentException("Couldn't determine type for " + root); -// } } - PrismBeanConverter beanConverter = prismContext.getBeanConverter(); - if (clazz != null && beanConverter.canProcess(clazz)) { - return beanConverter.unmarshall(root, clazz, context); + if (clazz != null && getBeanConverter().canProcess(clazz)) { + return getBeanConverter().unmarshall(root, clazz, context); } else { PrismValue prismValue = doParseItemValue(root); if (prismValue == null) { return null; - } else if (prismValue instanceof PrismPropertyValue) { - return (T) ((PrismPropertyValue) prismValue).getValue(); - } else if (prismValue instanceof PrismContainerValue) { - return (T) ((PrismContainerValue) prismValue).asContainerable(); - } else if (prismValue instanceof PrismReferenceValue) { - return (T) prismValue; // TODO ok? } else { - throw new IllegalStateException("Unsupported value: " + prismValue.getClass()); + return prismValue.getRealValue(); } } } + private PrismBeanConverter getBeanConverter() { + return prismContext.getBeanConverter(); + } + @SuppressWarnings("unchecked") T doParseRealValue() throws IOException, SchemaException { return (T) doParseRealValue(typeClass); @@ -242,10 +236,12 @@ List> doParseObjects() throws IOException, Sch return objects; } - @Deprecated - Object doParseAnyData() throws IOException, SchemaException { + Object doParseItemOrRealValue() throws IOException, SchemaException { RootXNode xnode = getLexicalProcessor().read(source, context); - return prismContext.getPrismUnmarshaller().parseAnyData(xnode, context); + if (itemDefinition != null || itemName != null || typeName != null || typeClass != null) { + throw new IllegalArgumentException("Item definition, item name, type name and type class must be null when calling parseItemOrRealValue."); + } + return prismContext.getPrismUnmarshaller().parseItemOrRealValue(xnode, context); } @NotNull diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplIO.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplIO.java index da5e13fd193..ce0dd3cbfdf 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplIO.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplIO.java @@ -78,9 +78,8 @@ public List> parseObjects() throws SchemaExcep return doParseObjects(); } - @Deprecated @Override - public Object parseAnyData() throws IOException, SchemaException { - return doParseAnyData(); + public Object parseItemOrRealValue() throws IOException, SchemaException { + return doParseItemOrRealValue(); } } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplNoIO.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplNoIO.java index d796bf2715f..36c25309b40 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplNoIO.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismParserImplNoIO.java @@ -177,11 +177,10 @@ public List> parseObjects() throws SchemaExcep } } - @Deprecated @Override - public Object parseAnyData() throws SchemaException { + public Object parseItemOrRealValue() throws SchemaException { try { - return doParseAnyData(); + return doParseItemOrRealValue(); } catch (IOException e) { throw new IllegalStateException(e); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismUnmarshaller.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismUnmarshaller.java index 450d4286c2a..0fcd3ca4c83 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismUnmarshaller.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismUnmarshaller.java @@ -25,10 +25,12 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.schema.PrismSchema; import com.evolveum.midpoint.prism.schema.SchemaRegistry; +import com.evolveum.midpoint.prism.util.RawTypeUtil; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType; +import com.evolveum.prism.xml.ns._public.types_3.RawType; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.Validate; @@ -103,8 +105,7 @@ PrismObject parseObject(MapXNode map, PrismObjectDefin return parseItemInternal(root.getSubnode(), itemInfo.getItemName(), itemInfo.getItemDefinition(), pc); } - @Deprecated - public Object parseAnyData(@NotNull RootXNode root, ParsingContext pc) throws SchemaException { + Object parseItemOrRealValue(@NotNull RootXNode root, ParsingContext pc) throws SchemaException { // is the type name explicitly specified? (if not, guess that we have a string) QName typeName = root.getTypeQName(); if (typeName != null) { @@ -134,12 +135,10 @@ public Object parseAnyData(@NotNull RootXNode root, ParsingContext pc) throws Sc private Item parseItemInternal(@NotNull XNode node, @NotNull QName itemName, ItemDefinition itemDefinition, @NotNull ParsingContext pc) throws SchemaException { Validate.isTrue(!(node instanceof RootXNode)); - if (itemDefinition == null) { // Assume property in a container with runtime definition - return PrismProperty.createRaw(node, itemName, prismContext); + if (itemDefinition == null || itemDefinition instanceof PrismPropertyDefinition) { + return parseProperty(node, itemName, (PrismPropertyDefinition) itemDefinition, pc); } else if (itemDefinition instanceof PrismContainerDefinition) { // also objects go here return parseContainer(node, itemName, (PrismContainerDefinition) itemDefinition, pc); - } else if (itemDefinition instanceof PrismPropertyDefinition) { - return parseProperty(node, itemName, (PrismPropertyDefinition) itemDefinition, pc); } else if (itemDefinition instanceof PrismReferenceDefinition) { return parseReference(node, itemName, (PrismReferenceDefinition) itemDefinition, pc); } else { @@ -263,13 +262,16 @@ private PrismContainerValue parseContainerValueFrom @NotNull private PrismProperty parseProperty(@NotNull XNode node, @NotNull QName itemName, - @NotNull PrismPropertyDefinition itemDefinition, @NotNull ParsingContext pc) throws SchemaException { + @Nullable PrismPropertyDefinition itemDefinition, @NotNull ParsingContext pc) throws SchemaException { Validate.isTrue(!(node instanceof RootXNode)); - PrismProperty property = itemDefinition.instantiate(); + PrismProperty property = itemDefinition != null ? + itemDefinition.instantiate() : + new PrismProperty(itemName, prismContext); + if (node instanceof ListXNode) { ListXNode listNode = (ListXNode) node; - if (!itemDefinition.isMultiValue() && listNode.size() > 1) { + if (itemDefinition != null && !itemDefinition.isMultiValue() && listNode.size() > 1) { throw new SchemaException("Attempt to store multiple values in single-valued property " + itemName); } for (XNode subNode : listNode) { @@ -295,7 +297,11 @@ private PrismProperty parseProperty(@NotNull XNode node, @NotNull QName i } private PrismPropertyValue parsePropertyValue(@NotNull XNode node, - @NotNull PrismPropertyDefinition definition, @NotNull ParsingContext pc) throws SchemaException { + @Nullable PrismPropertyDefinition definition, @NotNull ParsingContext pc) throws SchemaException { + + if (definition == null || definition.isAnyType()) { + return PrismPropertyValue.createRaw(node); + } T realValue; if (node instanceof PrimitiveXNode) { @@ -318,7 +324,7 @@ private T parsePropertyRealValueFromPrimitive(@NotNull PrimitiveXNode pri if (getBeanConverter().canProcess(typeName)) { // Primitive elements may also have complex Java representations (e.g. enums) realValue = getBeanConverter().unmarshallPrimitive(primitiveNode, typeName, pc); - } else { + } else if (!DOMUtil.XSD_ANYTYPE.equals(typeName)) { try { realValue = primitiveNode.getParsedValue(typeName, pc.getEvaluationMode()); } catch (SchemaException e) { @@ -326,9 +332,11 @@ private T parsePropertyRealValueFromPrimitive(@NotNull PrimitiveXNode pri + ".\nDefinition: " + definition.debugDump(), e); return null; } + } else { + realValue = (T) RawType.create(primitiveNode, prismContext); } - if (!isValueAllowed(realValue, definition.getAllowedValues())) { + if (!(realValue instanceof RawType) && !isValueAllowed(realValue, definition.getAllowedValues())) { pc.warnOrThrow(LOGGER, "Skipping unknown value of type " + typeName + ". Value: " + primitiveNode.getStringValue()); return null; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/PrimitiveXNode.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/PrimitiveXNode.java index 24a387f59cf..ac93514e4bc 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/PrimitiveXNode.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/xnode/PrimitiveXNode.java @@ -68,22 +68,12 @@ public PrimitiveXNode(T value) { public void parseValue(QName typeName, XNodeProcessorEvaluationMode mode) throws SchemaException { Validate.notNull(typeName, "Cannot parse primitive XNode without knowing its type"); if (valueParser != null) { - typeName = xsdAnyToString(typeName); value = valueParser.parse(typeName, mode); // Necessary. It marks that the value is parsed. It also frees some memory. valueParser = null; } } - // xsd:any type will be parsed as xsd:string (TODO reconsider!) - private QName xsdAnyToString(QName typeName) { - if (DOMUtil.XSD_ANYTYPE.equals(typeName)) { - return DOMUtil.XSD_STRING; - } else { - return typeName; - } - } - public T getValue() { return value; } @@ -161,7 +151,6 @@ public T getParsedValueWithoutRecording(QName typeName) throws SchemaException { if (isParsed()) { return value; } else { - typeName = xsdAnyToString(typeName); return valueParser.parse(typeName, XNodeProcessorEvaluationMode.STRICT); } } @@ -342,7 +331,7 @@ public boolean equals(Object obj) { String otherStringValue = String.valueOf(other.value); return otherStringValue.equals(thisStringValue); } else if (!other.isParsed() && isParsed()){ - String thisStringValue = String.valueOf(value);; + String thisStringValue = String.valueOf(value); String otherStringValue = other.getStringValue(); return thisStringValue.equals(otherStringValue); } diff --git a/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java b/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java index c5124f88b8e..c653c95be11 100644 --- a/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java +++ b/infra/prism/src/main/java/com/evolveum/prism/xml/ns/_public/types_3/RawType.java @@ -84,12 +84,12 @@ public PrismContext getPrismContext() { //region Parsing and serialization // itemDefinition may be null; in that case we do the best what we can public IV getParsedValue(@Nullable ItemDefinition itemDefinition, @Nullable QName itemName) throws SchemaException { - Validate.isTrue(itemDefinition != null || itemName != null); if (parsed != null) { return (IV) parsed; } else if (xnode != null) { IV value; - if (itemDefinition != null) { + if (itemDefinition != null + && !(itemDefinition instanceof PrismPropertyDefinition && ((PrismPropertyDefinition) itemDefinition).isAnyType())) { if (itemName == null) { itemName = itemDefinition.getName(); } @@ -100,20 +100,19 @@ public IV getParsedValue(@Null } else { value = null; } + xnode = null; + parsed = value; + return (IV) parsed; } else { - assert itemName != null; - PrismProperty subItem = PrismProperty.createRaw(xnode, itemName, prismContext); - value = (IV) subItem.getValue(); + // we don't really want to set 'parsed', as we didn't performed real parsing + return (IV) PrismPropertyValue.createRaw(xnode); } - xnode = null; - parsed = value; - return (IV) parsed; } else { return null; } } - public V getParsedRealValue(ItemDefinition itemDefinition, ItemPath itemPath) throws SchemaException { + public V getParsedRealValue(ID itemDefinition, ItemPath itemPath) throws SchemaException { if (parsed == null && xnode != null) { if (itemDefinition == null) { return prismContext.parserFor(xnode.toRootXNode()).parseRealValue(); // TODO what will be the result without definition? @@ -122,22 +121,26 @@ public V getParsedRealValue(ItemDefinition itemDef getParsedValue(itemDefinition, itemName); } } - if (parsed != null){ - if (parsed instanceof PrismPropertyValue){ - return (V) ((PrismPropertyValue) parsed).getValue(); - } else if (parsed instanceof PrismContainerValue){ - return (V) ((PrismContainerValue) parsed).asContainerable(); - } else if (parsed instanceof PrismReferenceValue){ - return (V) ((PrismReferenceValue) parsed).asReferencable(); - } + if (parsed != null) { + return parsed.getRealValue(); } - return null; - } - - + public T getParsedRealValue(@NotNull Class clazz) throws SchemaException { + if (parsed != null) { + if (clazz.isAssignableFrom(parsed.getClass())) { + return (T) parsed; + } else { + throw new IllegalArgumentException("Parsed value ("+parsed.getClass()+") is not assignable to "+clazz); + } + } else if (xnode != null) { + return (T) prismContext.parserFor(xnode.toRootXNode()).parseRealValue(clazz); + } else { + return null; + } + } + public Item getParsedItem(ID itemDefinition) throws SchemaException { Validate.notNull(itemDefinition); return getParsedItem(itemDefinition, itemDefinition.getName()); @@ -239,4 +242,8 @@ public static RawType create(String value, PrismContext prismContext) { return rv; } + public static RawType create(XNode node, PrismContext prismContext) { + return new RawType(node, prismContext); + } + } diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestDeltaConverter.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestDeltaConverter.java index 620f0842a9a..ec4c708fe6b 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestDeltaConverter.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestDeltaConverter.java @@ -274,7 +274,7 @@ public void testProtectedStringObjectDelta() throws Exception { RawType val = valueElements.get(0); MapXNode valXNode = (MapXNode) val.serializeToXNode(); PrimitiveXNode clearValueNode = (PrimitiveXNode) valXNode.get(ProtectedStringType.F_CLEAR_VALUE); - val.getParsedValue(null, new QName("dummy")); + val.getParsedValue(null, null); // System.out.println("clear value " + clearValueNode); assertEquals("Wrong element value", protectedString.getClearValue(), clearValueNode.getParsedValue(DOMUtil.XSD_STRING)); // List values = val.getContent(); diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestJaxbParsing.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestJaxbParsing.java index a7cb310914d..50a1d7aeb64 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestJaxbParsing.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestJaxbParsing.java @@ -241,7 +241,8 @@ public void testParseAnyValue() throws Exception { JAXBElement oValue = prismContext.parserFor(dataValue).xml().parseRealValueToJaxbElement(); System.out.println(dumpResult(dataValue, oValue)); - assertJaxbElement(oValue, SchemaConstantsGenerated.C_VALUE, String.class); + //assertJaxbElement(oValue, SchemaConstantsGenerated.C_VALUE, String.class); + assertJaxbElement(oValue, SchemaConstantsGenerated.C_VALUE, RawType.class); } private void assertJaxbElement(JAXBElement jaxbElement, QName name, Class clazz) { diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java index 99dd04dd27f..1f88dd194cf 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestQueryConvertor.java @@ -214,7 +214,7 @@ public void testAccountQueryCompositeOr() throws Exception { public void testConnectorQuery() throws Exception { displayTestTitle("testConnectorQuery"); SearchFilterType filterType = PrismTestUtil.parseAtomicValue(FILTER_CONNECTOR_BY_TYPE_FILE, SearchFilterType.COMPLEX_TYPE); - ObjectQuery query = null; + ObjectQuery query; try { query = QueryJaxbConvertor.createObjectQuery(ConnectorType.class, filterType, getPrismContext()); displayQuery(query); @@ -227,12 +227,6 @@ public void testConnectorQuery() throws Exception { QueryType convertedQueryType = toQueryType(query); displayQueryType(convertedQueryType); - } catch (SchemaException ex) { - LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); - throw ex; - } catch (RuntimeException ex) { - LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); - throw ex; } catch (Exception ex) { LOGGER.error("Error while converting query: {}", ex.getMessage(), ex); throw ex; diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/resource/TestParseResource.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/resource/TestParseResource.java index f7308551500..6caffe36c1f 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/resource/TestParseResource.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/resource/TestParseResource.java @@ -275,7 +275,7 @@ private void assertResourcePrism(PrismObject resource, boolean isS new ItemPath(new QName("extension"), new QName("extConnType")), path); PrismPropertyValue filterValue = (PrismPropertyValue) equalFilter.getValues().get(0); - assertEquals("Wrong filter value", "org.identityconnectors.ldap.LdapConnector", ((String) filterValue.getValue()).trim()); + assertEquals("Wrong filter value", "org.identityconnectors.ldap.LdapConnector", ((RawType) filterValue.getValue()).getParsedRealValue(String.class).trim()); } EvaluationTimeType resolutionTime = connectorRefVal.getResolutionTime(); if (isSimple) { diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java index ee49cf8ecb2..45098cc667b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/scripting/ScriptingExpressionEvaluator.java @@ -21,7 +21,6 @@ import com.evolveum.midpoint.model.impl.scripting.expressions.SelectEvaluator; import com.evolveum.midpoint.model.impl.scripting.helpers.JaxbHelper; import com.evolveum.midpoint.prism.Item; -import com.evolveum.midpoint.prism.ParsingContext; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.marshaller.QueryConvertor; import com.evolveum.midpoint.prism.query.ObjectFilter; @@ -257,7 +256,7 @@ private Data executeSequence(ExpressionSequenceType sequence, Data input, Execut public Data evaluateConstantExpression(RawType constant, ExecutionContext context, OperationResult result) throws ScriptExecutionException { try { - Object value = prismContext.parserFor(constant.getXnode().toRootXNode()).parseAnyData(); + Object value = prismContext.parserFor(constant.getXnode().toRootXNode()).parseItemOrRealValue(); if (value instanceof Item) { return Data.create((Item) value); } else { diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasic.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasic.java index f8e43d89fa5..80a73e86bdb 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasic.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/scripting/TestScriptingBasic.java @@ -160,7 +160,7 @@ public void test120Log() throws Exception { } private PrismProperty parseAnyData(File file) throws IOException, SchemaException { - return (PrismProperty) prismContext.parserFor(file).parseAnyData(); + return (PrismProperty) prismContext.parserFor(file).parseItemOrRealValue(); } @Test diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/SingleItemSerializationSafeContainerImpl.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/SingleItemSerializationSafeContainerImpl.java index 3d4ee71f5fa..ff4baaf469d 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/SingleItemSerializationSafeContainerImpl.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/SingleItemSerializationSafeContainerImpl.java @@ -115,7 +115,7 @@ public T getValue() { if (encodingScheme == EncodingScheme.PRISM) { try { - actualValue = (T) prismContext.parserFor(valueForStorageWhenEncoded).xml().parseAnyData(); + actualValue = (T) prismContext.parserFor(valueForStorageWhenEncoded).xml().parseItemOrRealValue(); if (actualValue instanceof Item) { Item item = (Item) actualValue; if (item.isEmpty()) {