diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExpressionWrapper.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/ExpressionWrapper.java similarity index 75% rename from infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExpressionWrapper.java rename to infra/prism/src/main/java/com/evolveum/midpoint/prism/ExpressionWrapper.java index ba5cb17df7c..01a557b9d60 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/ExpressionWrapper.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/ExpressionWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2014 Evolveum + * Copyright (c) 2010-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,9 @@ * limitations under the License. */ -package com.evolveum.midpoint.prism.query; +package com.evolveum.midpoint.prism; + +import com.evolveum.midpoint.util.PrettyPrinter; /** * @author mederly @@ -30,4 +32,11 @@ public Object getExpression() { public void setExpression(Object expression) { this.expression = expression; } + + @Override + public String toString() { + return expression==null?"ExpressionWrapper(null)":PrettyPrinter.prettyPrint(expression); + } + + } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java index f564669552e..37b7a1a5ca9 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismConstants.java @@ -122,4 +122,6 @@ public class PrismConstants { public static final boolean EQUALS_DEFAULT_IGNORE_METADATA = true; public static final boolean EQUALS_DEFAULT_IS_LITERAL = false; + + public static final String EXPRESSION_LOCAL_PART = "expression"; } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismProperty.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismProperty.java index 5bf1de716b0..c0543b9e7a8 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismProperty.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/PrismProperty.java @@ -519,6 +519,8 @@ public String debugDump(int indent) { if (value.isRaw()) { sb.append(formatRawValueForDump(value.getRawElement())); sb.append(" (raw)"); + } else if (value.getExpression() != null) { + sb.append(" (expression)"); } else { T realValue = value.getValue(); if (realValue instanceof DebugDumpable) { @@ -546,6 +548,8 @@ public String debugDump(int indent) { if (value.isRaw()) { sb.append(formatRawValueForDump(value.getRawElement())); sb.append(" (raw)"); + } else if (value.getExpression() != null) { + sb.append(" (expression)"); } else { if (DebugUtil.isDetailedDebugDump()) { sb.append(PrettyPrinter.prettyPrint(value)); 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 3b696cb08f9..6c0911901d6 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Evolveum + * Copyright (c) 2010-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,26 +60,29 @@ public class PrismPropertyValue extends PrismValue implements DebugDumpable, // We can't do anything smarter, as we don't have definition nor prism context. So we store the raw // elements here and process them later (e.g. during applyDefinition or getting a value with explicit type). private XNode rawElement; + + @Nullable private ExpressionWrapper expression; public PrismPropertyValue(T value) { this(value, null, null); } public PrismPropertyValue(T value, PrismContext prismContext) { - this(value, prismContext, null, null); + this(value, prismContext, null, null, null); } public PrismPropertyValue(T value, OriginType type, Objectable source) { - this(value, null, type, source); + this(value, null, type, source, null); } - public PrismPropertyValue(T value, PrismContext prismContext, OriginType type, Objectable source) { + public PrismPropertyValue(T value, PrismContext prismContext, OriginType type, Objectable source, ExpressionWrapper expression) { super(type, source); if (value instanceof PrismPropertyValue) { throw new IllegalArgumentException("Probably problem somewhere, encapsulating property " + "value object to another property value."); } this.value = value; + this.expression = expression; checkValue(); } @@ -170,11 +173,25 @@ public boolean isRaw() { return rawElement != null; } + @Nullable + public ExpressionWrapper getExpression() { + return expression; + } + + public void setExpression(@Nullable ExpressionWrapper expression) { + this.expression = expression; + } + @Override public void applyDefinition(ItemDefinition definition) throws SchemaException { PrismPropertyDefinition propertyDefinition = (PrismPropertyDefinition) definition; if (propertyDefinition != null && !propertyDefinition.isAnyType() && rawElement != null) { value = (T) parseRawElementToNewRealValue(this, propertyDefinition); + if (value == null) { + // Be careful here. Expression element can be legal sub-element of complex properties. + // Therefore parse expression only if there is no legal value. + expression = PrismUtil.parseExpression(rawElement, prismContext); + } rawElement = null; } } @@ -235,6 +252,9 @@ void checkValue() { // Cannot really check raw values return; } + if (expression != null) { + return; + } if (value == null) { // can be used not because of prism forms in gui (will be fixed later [lazyman] // throw new IllegalArgumentException("Null value in "+this); @@ -274,8 +294,8 @@ public void checkConsistenceInternal(Itemable rootItem, boolean requireDefinitio if (prohibitRaw && rawElement != null) { throw new IllegalStateException("Raw element in property value "+this+" ("+myPath+" in "+rootItem+")"); } - if (value == null && rawElement == null) { - throw new IllegalStateException("Neither value nor raw element specified in property value "+this+" ("+myPath+" in "+rootItem+")"); + if (value == null && rawElement == null && expression == null) { + throw new IllegalStateException("Neither value, expression nor raw element specified in property value "+this+" ("+myPath+" in "+rootItem+")"); } if (value != null && rawElement != null) { throw new IllegalStateException("Both value and raw element specified in property value "+this+" ("+myPath+" in "+rootItem+")"); @@ -592,6 +612,13 @@ public String debugDump(int indent) { } debugDumpValue(sb, indent, value, prismContext); } + } else if (expression != null) { + if (!wasIndent) { + DebugUtil.indentDebugDump(sb, indent); + } + sb.append("expression: "); + // TODO: nicer output + sb.append(expression); } else { if (!wasIndent) { DebugUtil.indentDebugDump(sb, indent); @@ -640,10 +667,17 @@ private void dumpSuffix(StringBuilder builder) { builder.append(", raw element: "); builder.append(PrettyPrinter.prettyPrint(getRawElement())); } + if (getExpression() != null) { + builder.append(", expression: "); + builder.append(getExpression()); + } } @Override public String toHumanReadableString() { + if (value == null && expression != null) { + return ("expression("+expression+")"); + } return PrettyPrinter.prettyPrint(value); } diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/BeanUnmarshaller.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/BeanUnmarshaller.java index 06514fdfa00..dc5e317d1c1 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/BeanUnmarshaller.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/BeanUnmarshaller.java @@ -163,6 +163,16 @@ private T unmarshalInternal(@NotNull XNode xnode, @NotNull Class beanClas throw new SchemaException("Cannot convert primitive value to bean of type " + beanClass); } } else { + + if (beanClass.getPackage().getName().equals("java.lang")) { + // We obviously have primitive data type, but we have are asked to unmarshall from map xnode + // TODO: more robust implementation + // TODO: look for "value" subnode with primitive value and try that. + // This is most likely attempt to parse primitive value with dynamic expression. + // Therefore just ignore entire map content. + return null; + } + @SuppressWarnings("unchecked") MapUnmarshaller unmarshaller = specialMapUnmarshallers.get(beanClass); if (xnode instanceof MapXNode && unmarshaller != null) { // TODO: what about special unmarshaller + hetero list? diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismMarshaller.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismMarshaller.java index 7486ce09d63..c319b8dc0fa 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismMarshaller.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/PrismMarshaller.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.schema.SchemaRegistry; +import com.evolveum.midpoint.prism.util.PrismUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.prism.xnode.*; import com.evolveum.midpoint.util.DOMUtil; @@ -388,6 +389,12 @@ private QName createReferenceQName(QName qname, String namespace) { //region Serializing properties - specific functionality private XNode serializePropertyValue(@NotNull PrismPropertyValue value, PrismPropertyDefinition definition, QName typeNameIfNoDefinition) throws SchemaException { @Nullable QName typeName = definition != null ? definition.getTypeName() : typeNameIfNoDefinition; + ExpressionWrapper expression = value.getExpression(); + if (expression != null) { + // Store expression, not the value. In this case the value (if any) is + // a transient product of the expression evaluation. + return createExpressionXNode(expression); + } T realValue = value.getValue(); if (realValue instanceof PolyString) { return serializePolyString((PolyString) realValue); @@ -408,7 +415,7 @@ private XNode serializePropertyValue(@NotNull PrismPropertyValue value, P } } - private XNode serializePolyString(PolyString realValue) { + private XNode serializePolyString(PolyString realValue) { PrimitiveXNode xprim = new PrimitiveXNode<>(); xprim.setValue(realValue, PolyStringType.COMPLEX_TYPE); return xprim; @@ -444,6 +451,11 @@ private PrimitiveXNode createPrimitiveXNode(T val, QName type) { xprim.setValue(val, type); return xprim; } + + @NotNull + private XNode createExpressionXNode(@NotNull ExpressionWrapper expression) { + return PrismUtil.serializeExpression(expression); + } @NotNull private SchemaRegistry getSchemaRegistry() { 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 75a8c6cd334..4316bda9b95 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Evolveum + * Copyright (c) 2010-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import com.evolveum.prism.xml.ns._public.types_3.SchemaDefinitionType; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,6 +38,7 @@ import javax.xml.XMLConstants; import javax.xml.namespace.QName; import java.util.Map.Entry; +import java.util.Set; public class PrismUnmarshaller { @@ -370,7 +372,14 @@ private PrismPropertyValue parsePropertyValue(@NotNull XNode node, return null; } if (realValue == null) { - return null; + // Be careful here. Expression element can be legal sub-element of complex properties. + // Therefore parse expression only if there is no legal value. + ExpressionWrapper expression = PrismUtil.parseExpression(node, prismContext); + if (expression != null) { + PrismPropertyValue ppv = new PrismPropertyValue<>(null, prismContext, null, null, expression); + return ppv; + + } } PrismPropertyValue ppv = new PrismPropertyValue<>(realValue); ppv.setPrismContext(prismContext); diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/QueryConvertor.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/QueryConvertor.java index c017047288c..fde81d2a9ed 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/QueryConvertor.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/marshaller/QueryConvertor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2016 Evolveum + * Copyright (c) 2010-2017 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.query.OrgFilter.Scope; +import com.evolveum.midpoint.prism.util.PrismUtil; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.exception.SchemaException; @@ -496,18 +497,8 @@ private static RefFilter parseRefFilter(MapXNode claus private static ExpressionWrapper parseExpression(MapXNode xmap, PrismContext prismContext) throws SchemaException { Entry expressionEntry = xmap.getSingleEntryThatDoesNotMatch( - ELEMENT_VALUE, ELEMENT_MATCHING, ELEMENT_PATH); - if (expressionEntry != null) { - RootXNode expressionRoot = new RootXNode(expressionEntry); - PrismPropertyValue expressionPropertyValue = prismContext.parserFor(expressionRoot).parseItemValue(); - ExpressionWrapper expressionWrapper = new ExpressionWrapper(); - expressionWrapper.setExpression(expressionPropertyValue.getValue()); - return expressionWrapper; - } - - return null; - + return PrismUtil.parseExpression(expressionEntry, prismContext); } private static SubstringFilter parseSubstringFilter(MapXNode clauseXMap, PrismContainerDefinition pcd, boolean preliminaryParsingOnly, PrismContext prismContext) @@ -841,8 +832,7 @@ private static MapXNode seriali ExpressionWrapper xexpression = filter.getExpression(); if (xexpression != null) { - //map.merge(xexpression); - //TODO serialize expression + map.merge(PrismUtil.serializeExpression(xexpression)); } return map; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FullTextFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FullTextFilter.java index 4a801630e5c..f5b5b42167e 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FullTextFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/FullTextFilter.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.prism.query; +import com.evolveum.midpoint.prism.ExpressionWrapper; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.match.MatchingRuleRegistry; import com.evolveum.midpoint.util.DebugUtil; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java index c8085bf03ce..a192b4b0d1b 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/GreaterFilter.java @@ -15,6 +15,7 @@ */ package com.evolveum.midpoint.prism.query; +import com.evolveum.midpoint.prism.ExpressionWrapper; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContainerValue; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java index 1928b967237..2f0fc4283c2 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/InOidFilter.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Iterator; +import com.evolveum.midpoint.prism.ExpressionWrapper; import com.evolveum.midpoint.prism.PrismContainer; import com.evolveum.midpoint.prism.PrismObject; import org.apache.commons.lang.StringUtils; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java index 546a55f86ae..8dac6b4ff50 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/query/LessFilter.java @@ -16,6 +16,7 @@ package com.evolveum.midpoint.prism.query; +import com.evolveum.midpoint.prism.ExpressionWrapper; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismPropertyDefinition; diff --git a/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismUtil.java b/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismUtil.java index 527628ad8b0..593e178c2a7 100644 --- a/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismUtil.java +++ b/infra/prism/src/main/java/com/evolveum/midpoint/prism/util/PrismUtil.java @@ -23,6 +23,9 @@ import com.evolveum.midpoint.prism.polystring.PolyString; import com.evolveum.midpoint.prism.polystring.PolyStringNormalizer; import com.evolveum.midpoint.prism.xml.XsdTypeMapper; +import com.evolveum.midpoint.prism.xnode.MapXNode; +import com.evolveum.midpoint.prism.xnode.RootXNode; +import com.evolveum.midpoint.prism.xnode.XNode; import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; @@ -234,4 +237,35 @@ public String toString() { } }; } + + public static ExpressionWrapper parseExpression(XNode node, PrismContext prismContext) throws SchemaException { + if (!(node instanceof MapXNode)) { + return null; + } + if (((MapXNode)node).isEmpty()) { + return null; + } + for (Entry entry: ((MapXNode)node).entrySet()) { + if (PrismConstants.EXPRESSION_LOCAL_PART.equals(entry.getKey().getLocalPart())) { + return parseExpression(entry, prismContext); + } + } + return null; + } + + public static ExpressionWrapper parseExpression(Entry expressionEntry, PrismContext prismContext) throws SchemaException { + if (expressionEntry == null) { + return null; + } + RootXNode expressionRoot = new RootXNode(expressionEntry); + PrismPropertyValue expressionPropertyValue = prismContext.parserFor(expressionRoot).parseItemValue(); + ExpressionWrapper expressionWrapper = new ExpressionWrapper(); + expressionWrapper.setExpression(expressionPropertyValue.getValue()); + return expressionWrapper; + } + + public static MapXNode serializeExpression(ExpressionWrapper expression) { + // TODO + return new MapXNode(); + } } diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd index 7db8d223518..953692a61d5 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-core-3.xsd @@ -6684,6 +6684,8 @@ + + diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestConstants.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestConstants.java index 807c7c10dc4..18fed5c5c4a 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestConstants.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/TestConstants.java @@ -51,6 +51,7 @@ public class TestConstants { public static final String RESOURCE_FILE_BASENAME = "resource-opendj"; public static final String RESOURCE_FILE_SIMPLE_BASENAME = "resource-opendj-simple"; public static final File RESOURCE_FILE = new File(TestConstants.COMMON_DIR, "xml/ns/resource-opendj.xml"); + public static final String RESOURCE_FILE_EXPRESSION_BASENAME = "resource-expression"; public static final String RESOURCE_OID = "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; public static final String RESOURCE_NAMESPACE = "http://midpoint.evolveum.com/xml/ns/public/resource/instance/ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff"; diff --git a/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/TestParseResource.java b/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/TestParseResource.java index 347703f94c0..3b3a2066a2e 100644 --- a/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/TestParseResource.java +++ b/infra/schema/src/test/java/com/evolveum/midpoint/schema/parser/TestParseResource.java @@ -22,7 +22,6 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; import com.evolveum.midpoint.prism.query.EqualFilter; -import com.evolveum.midpoint.prism.query.ExpressionWrapper; import com.evolveum.midpoint.prism.query.ObjectFilter; import com.evolveum.midpoint.prism.util.ItemPathUtil; import com.evolveum.midpoint.prism.util.PrismAsserts; @@ -203,6 +202,103 @@ public void testSchemaRoundtrip() throws Exception { } + @Test + public void testParseResourceFileExpression() throws Exception { + final String TEST_NAME = "testParseResourceFileExpression"; + displayTestTitle(TEST_NAME); + + // GIVEN + PrismContext prismContext = getPrismContext(); + + // WHEN + PrismObject resource = prismContext.parseObject(getFile(TestConstants.RESOURCE_FILE_EXPRESSION_BASENAME)); + + // THEN + System.out.println("Parsed resource:"); + System.out.println(resource.debugDump()); + + resource.checkConsistence(); + + AssertJUnit.assertEquals("Wrong oid (prism)", TestConstants.RESOURCE_OID, resource.getOid()); + PrismObjectDefinition resourceDefinition = resource.getDefinition(); + assertNotNull("No resource definition", resourceDefinition); + PrismAsserts.assertObjectDefinition(resourceDefinition, new QName(SchemaConstantsGenerated.NS_COMMON, "resource"), + ResourceType.COMPLEX_TYPE, ResourceType.class); + assertEquals("Wrong class in resource", ResourceType.class, resource.getCompileTimeClass()); + ResourceType resourceType = resource.asObjectable(); + assertNotNull("asObjectable resulted in null", resourceType); + + assertPropertyValue(resource, "name", PrismTestUtil.createPolyString("Resource with expressions")); + + PrismContainer configurationContainer = resource.findContainer(ResourceType.F_CONNECTOR_CONFIGURATION); + assertContainerDefinition(configurationContainer, "configuration", ConnectorConfigurationType.COMPLEX_TYPE, 1, 1); + PrismContainerValue configContainerValue = configurationContainer.getValue(); + List> configItems = configContainerValue.getItems(); + assertEquals("Wrong number of config items", 1, configItems.size()); + + PrismContainer ldapConfigPropertiesContainer = configurationContainer.findContainer(ICFC_CONFIGURATION_PROPERTIES); + assertNotNull("No icfcldap:configurationProperties container", ldapConfigPropertiesContainer); + PrismContainerDefinition ldapConfigPropertiesContainerDef = ldapConfigPropertiesContainer.getDefinition(); + assertNotNull("No icfcldap:configurationProperties container definition", ldapConfigPropertiesContainerDef); + assertEquals("icfcldap:configurationProperties container definition maxOccurs", 1, ldapConfigPropertiesContainerDef.getMaxOccurs()); + List> ldapConfigPropItems = ldapConfigPropertiesContainer.getValue().getItems(); + assertEquals("Wrong number of ldapConfigPropItems items", 7, ldapConfigPropItems.size()); + + PrismProperty hostProp = findProp(ldapConfigPropItems, "host"); + assertRaw(hostProp); + hostProp.applyDefinition(new PrismPropertyDefinitionImpl<>(new QName("whatever","host"), DOMUtil.XSD_STRING, prismContext)); + assertNotRaw(hostProp); + assertExpression(hostProp, "const"); + + PrismProperty baseContextsProp = findProp(ldapConfigPropItems, "baseContexts"); + assertRaw(baseContextsProp); + baseContextsProp.applyDefinition(new PrismPropertyDefinitionImpl<>(new QName("whatever","baseContexts"), DOMUtil.XSD_STRING, prismContext)); + assertNotRaw(baseContextsProp); + assertExpression(baseContextsProp, "script"); + + PrismContainer schemaContainer = resource.findContainer(ResourceType.F_SCHEMA); + assertNull("Schema sneaked in", schemaContainer); + + PrismContainer schemaHandlingContainer = resource.findContainer(ResourceType.F_SCHEMA_HANDLING); + assertNull("SchemaHandling sneaked in", schemaHandlingContainer); + + } + + private void assertRaw(PrismProperty prop) { + assertTrue("Prop "+prop+" no raw", prop.isRaw()); + } + + private void assertNotRaw(PrismProperty prop) { + assertFalse("Prop "+prop+" raw (unexpected)", prop.isRaw()); + } + + private PrismProperty findProp(List> items, String local) { + for (Item item: items) { + if (local.equals(item.getElementName().getLocalPart())) { + return (PrismProperty) item; + } + } + fail("No item "+local); + return null; // not reached + } + + private void assertExpression(PrismProperty prop, String evaluatorName) { + System.out.println("Prop:"); + System.out.println(prop.debugDump(1)); + PrismPropertyValue pval = prop.getValue(); + ExpressionWrapper expressionWrapper = pval.getExpression(); + assertNotNull("No expression wrapper in "+prop, expressionWrapper); + Object expressionObj = expressionWrapper.getExpression(); + assertNotNull("No expression in "+prop, expressionObj); + System.out.println("- Expression: "+expressionObj); + if (namespaces) { + assertTrue("Wrong expression type ("+language+","+(namespaces?"ns":"no-ns") + ") : " +expressionObj.getClass(), expressionObj instanceof ExpressionType); + ExpressionType expressionType = (ExpressionType)expressionObj; + JAXBElement evaluatorElement = expressionType.getExpressionEvaluator().iterator().next(); + assertEquals("Wrong expression evaluator name", evaluatorName, evaluatorElement.getName().getLocalPart()); + } + } + @Override protected void assertPrismContainerValueLocal(PrismContainerValue value) throws SchemaException { //assertResource(object.asContainerable().asPrismObject(), true, true); diff --git a/infra/schema/src/test/resources/common/json/no-ns/resource-expression.json b/infra/schema/src/test/resources/common/json/no-ns/resource-expression.json new file mode 100644 index 00000000000..70bd88458ab --- /dev/null +++ b/infra/schema/src/test/resources/common/json/no-ns/resource-expression.json @@ -0,0 +1,38 @@ +{ + "resource" : { + "oid" : "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff", + "name" : "Resource with expressions", + "connectorRef" : { + "type" : "http://midpoint.evolveum.com/xml/ns/public/common/common-3#ConnectorType", + "filter" : { + "equal" : { + "path" : "extension/extConnType", + "value" : "org.identityconnectors.ldap.LdapConnector" + } + } + }, + "connectorConfiguration" : { + "configurationProperties" : { + "port" : "389", + "host" : { + "expression" : { + "const" : "ldapHostname" + } + }, + "baseContexts" : { + "expression" : { + "script" : { + "code" : "'dc='+basic.const('orgname')+',dc=com'" + } + } + }, + "principal" : "cn=directory manager", + "credentials" : { + "clearValue" : "secret" + }, + "vlvSortAttribute" : "uid", + "accountOperationalAttributes" : "ds-pwp-account-disabled" + } + } + } +} diff --git a/infra/schema/src/test/resources/common/json/ns/resource-expression.json b/infra/schema/src/test/resources/common/json/ns/resource-expression.json new file mode 100644 index 00000000000..f82116ea548 --- /dev/null +++ b/infra/schema/src/test/resources/common/json/ns/resource-expression.json @@ -0,0 +1,45 @@ +{ + "@ns" : "http://midpoint.evolveum.com/xml/ns/public/common/common-3", + "resource" : { + "oid" : "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff", + "name" : "Resource with expressions", + "connectorRef" : { + "type" : "http://midpoint.evolveum.com/xml/ns/public/common/common-3#ConnectorType", + "filter" : { + "@ns" : "http://prism.evolveum.com/xml/ns/public/query-3", + "equal" : { + "path" : "declare namespace x='http://x/'; extension/x:extConnType", + "value" : "org.identityconnectors.ldap.LdapConnector" + } + } + }, + "connectorConfiguration" : { + "@ns" : "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3", + "configurationProperties" : { + "@ns" : "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/org.forgerock.openicf.connectors.ldap.ldap/org.identityconnectors.ldap.LdapConnector", + "port" : "389", + "host" : { + "@ns" : "http://midpoint.evolveum.com/xml/ns/public/common/common-3", + "expression" : { + "const" : "ldapHostname" + } + }, + "baseContexts" : { + "@ns" : "http://midpoint.evolveum.com/xml/ns/public/common/common-3", + "expression" : { + "script" : { + "code" : "'dc='+basic.const('orgname')+',dc=com'" + } + } + }, + "principal" : "cn=directory manager", + "credentials" : { + "@ns" : "http://prism.evolveum.com/xml/ns/public/types-3", + "clearValue" : "secret" + }, + "vlvSortAttribute" : "uid", + "accountOperationalAttributes" : "ds-pwp-account-disabled" + } + } + } +} diff --git a/infra/schema/src/test/resources/common/xml/no-ns/resource-expression.xml b/infra/schema/src/test/resources/common/xml/no-ns/resource-expression.xml new file mode 100644 index 00000000000..52825fa79fe --- /dev/null +++ b/infra/schema/src/test/resources/common/xml/no-ns/resource-expression.xml @@ -0,0 +1,60 @@ + + + + + + + + Resource with expressions + + + + + extension/extConnType + + org.identityconnectors.ldap.LdapConnector + + + + + + + + 389 + + + ldapHostname + + + + + + + + cn=directory manager + + secret + + uid + ds-pwp-account-disabled + + + + + diff --git a/infra/schema/src/test/resources/common/xml/ns/resource-expression.xml b/infra/schema/src/test/resources/common/xml/ns/resource-expression.xml new file mode 100644 index 00000000000..839ecbbee2c --- /dev/null +++ b/infra/schema/src/test/resources/common/xml/ns/resource-expression.xml @@ -0,0 +1,79 @@ + + + + + + + + Resource with expressions + + + + + extension/x:extConnType + + org.identityconnectors.ldap.LdapConnector + + + + + + + + + + + + 389 + + + ldapHostname + + + + + + + + cn=directory manager + + secret + + uid + ds-pwp-account-disabled + + + + + diff --git a/infra/schema/src/test/resources/common/yaml/no-ns/resource-expression.yaml b/infra/schema/src/test/resources/common/yaml/no-ns/resource-expression.yaml new file mode 100644 index 00000000000..5eb5c654ada --- /dev/null +++ b/infra/schema/src/test/resources/common/yaml/no-ns/resource-expression.yaml @@ -0,0 +1,25 @@ +--- +resource: + oid: "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff" + name: "Resource with expressions" + connectorRef: + type: "http://midpoint.evolveum.com/xml/ns/public/common/common-3#ConnectorType" + filter: + equal: + path: "extension/extConnType" + value: "org.identityconnectors.ldap.LdapConnector" + connectorConfiguration: + configurationProperties: + port: "389" + host: + expression: + const: "ldapHostname" + baseContexts: + expression: + script: + code: "'dc='+basic.const('orgname')+',dc=com'" + principal: "cn=directory manager" + credentials: + clearValue: "secret" + vlvSortAttribute: "uid" + accountOperationalAttributes: "ds-pwp-account-disabled" diff --git a/infra/schema/src/test/resources/common/yaml/ns/resource-expression.yaml b/infra/schema/src/test/resources/common/yaml/ns/resource-expression.yaml new file mode 100644 index 00000000000..f1eb1ce5bed --- /dev/null +++ b/infra/schema/src/test/resources/common/yaml/ns/resource-expression.yaml @@ -0,0 +1,32 @@ +--- +'@ns': "http://midpoint.evolveum.com/xml/ns/public/common/common-3" +resource: + oid: "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff" + name: "Resource with expressions" + connectorRef: + type: "http://midpoint.evolveum.com/xml/ns/public/common/common-3#ConnectorType" + filter: + '@ns': "http://prism.evolveum.com/xml/ns/public/query-3" + equal: + path: "declare namespace x='http://x/'; extension/x:extConnType" + value: "org.identityconnectors.ldap.LdapConnector" + connectorConfiguration: + '@ns': "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3" + configurationProperties: + '@ns': "http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/org.forgerock.openicf.connectors.ldap.ldap/org.identityconnectors.ldap.LdapConnector" + port: "389" + host: + '@ns': "http://midpoint.evolveum.com/xml/ns/public/common/common-3" + expression: + const: "ldapHostname" + baseContexts: + '@ns': "http://midpoint.evolveum.com/xml/ns/public/common/common-3" + expression: + script: + code: "'dc='+basic.const('orgname')+',dc=com'" + principal: "cn=directory manager" + credentials: + '@ns': "http://prism.evolveum.com/xml/ns/public/types-3" + clearValue: "secret" + vlvSortAttribute: "uid" + accountOperationalAttributes: "ds-pwp-account-disabled"