Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
KaterynaHonchar committed Nov 14, 2017
2 parents 76b4668 + df8f26c commit 930048c
Show file tree
Hide file tree
Showing 37 changed files with 1,302 additions and 390 deletions.
Expand Up @@ -22,7 +22,7 @@
import org.apache.wicket.feedback.FeedbackMessagesModel;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.Model;

import com.evolveum.midpoint.gui.api.component.result.OpResult;
import com.evolveum.midpoint.gui.api.component.result.OperationResultPanel;
Expand All @@ -48,8 +48,8 @@ protected void populateItem(final ListItem<FeedbackMessage> item) {
final FeedbackMessage message = item.getModelObject();

if (message.getMessage() instanceof OpResult) {
OperationResultPanel panel = new OperationResultPanel("message",
new PropertyModel<OpResult>(item.getModel(), "message"), getPage()) {
final OpResult opResult = (OpResult) message.getMessage();
OperationResultPanel panel = new OperationResultPanel("message", Model.of(opResult), getPage()) {

private static final long serialVersionUID = 1L;

Expand All @@ -60,7 +60,7 @@ public void close(AjaxRequestTarget target) {
}

protected void onAfterRender() {
((OpResult) message.getMessage()).setAlreadyShown(true);
opResult.setAlreadyShown(true);
super.onAfterRender();
};
};
Expand All @@ -69,13 +69,13 @@ protected void onAfterRender() {
private static final long serialVersionUID = 1L;

public boolean isVisible() {
return !((OpResult) item.getModelObject().getMessage()).isAlreadyShown();
return !opResult.isAlreadyShown();
};
});

panel.setOutputMarkupId(true);
item.add(panel);
} else if (!(message.getMessage() instanceof OpResult)) {
} else {

message.markRendered();
ValidationErrorPanel validationPanel = new ValidationErrorPanel("message", item.getModel()) {
Expand Down
Expand Up @@ -433,10 +433,10 @@ protected void appendOriginDump(StringBuilder builder) {
}
}

public static <T> Set<T> getRealValuesOfCollection(Collection<PrismPropertyValue<T>> collection) {
public static <T> Set<T> getRealValuesOfCollection(Collection<? extends PrismValue> collection) {
Set<T> retval = new HashSet<T>(collection.size());
for (PrismPropertyValue<T> value : collection) {
retval.add(value.getValue());
for (PrismValue value : collection) {
retval.add(value.getRealValue());
}
return retval;
}
Expand Down
Expand Up @@ -46,6 +46,7 @@ public class ExpressionConstants {
public static final QName VAR_PRISM_CONTEXT = new QName(SchemaConstants.NS_C, "prismContext");
public static final QName VAR_CONFIGURATION = new QName(SchemaConstants.NS_C, "configuration");
public static final QName VAR_ENTITLEMENT = new QName(SchemaConstants.NS_C, "entitlement");
public static final QName VAR_FILE = new QName(SchemaConstants.NS_C, "file");

/**
* User that is currently executing the operation.
Expand Down
Expand Up @@ -6658,19 +6658,32 @@
<a:since>3.7</a:since>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<!-- TODO: later
<xsd:sequence>
<xsd:element name="macro" type="tns:ProvisioningScriptArgumentType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Command-line macro. Any occurence of the macro will be replaced in the command-line code.
The order of arguments is not significant.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- TODO: later
<xsd:element name="argument" type="tns:ProvisioningScriptArgumentType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Script arguments. The arguments will passed to the script
in any way suitable for the script. The argument name
is "local" to the script (script-specific). Script name
is "local" to the script (script-specific). Argument name
must be unique in the argument set.
The order of arguments is not significant.
</xsd:documentation>
</xsd:annotation>
</xsd:element> -->
</xsd:element>
<xsd:element name="environment" type="tns:ProvisioningScriptArgumentType" minOccurs="0" maxOccurs="unbounded">
</xsd:element>
-->
<xsd:element name="executionMethod" type="tns:CommandLineExecutionMethod">
</xsd:element>
<xsd:element name="code" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Expand All @@ -6684,6 +6697,43 @@
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:simpleType name="CommandLineExecutionMethod">
<xsd:annotation>
<xsd:documentation>
TODO
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumClass/>
</xsd:appinfo>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="exec">
<xsd:annotation>
<xsd:documentation>
<p>
Plain exececution using OS services (exec).
</p>
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="EXEC"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="shell">
<xsd:annotation>
<xsd:documentation>
<p>
Execution using UNIX-like shell (e.g. bash)
</p>
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="SHELL"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>

<xsd:complexType name="ConnectorConfigurationType">
<xsd:annotation>
Expand Down
Expand Up @@ -7,6 +7,7 @@ public class MidPointTestConstants {
public static final String TEST_RESOURCES_PATH = "src/test/resources";
public static File TEST_RESOURCES_DIR = new File (TEST_RESOURCES_PATH);
public static File OBJECTS_DIR = new File(TEST_RESOURCES_DIR, "objects");
public static final String TARGET_DIR_PATH = "target";

// copied from TestProtector - unfortunately these values are needed both in prism and in other modules
public static final String KEYSTORE_PATH = "src/test/resources/keystore.jceks";
Expand Down
Expand Up @@ -15,6 +15,7 @@
*/
package com.evolveum.midpoint.model.common.expression.functions;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
Expand All @@ -25,10 +26,18 @@
import org.apache.commons.lang.Validate;

import com.evolveum.midpoint.prism.ItemDefinition;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismPropertyDefinitionImpl;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple;
import com.evolveum.midpoint.prism.polystring.PolyString;
import com.evolveum.midpoint.prism.util.JavaTypeConverter;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.prism.xml.XsdTypeMapper;
import com.evolveum.midpoint.repo.common.expression.Expression;
import com.evolveum.midpoint.repo.common.expression.ExpressionEvaluationContext;
import com.evolveum.midpoint.repo.common.expression.ExpressionFactory;
import com.evolveum.midpoint.repo.common.expression.ExpressionUtil;
import com.evolveum.midpoint.repo.common.expression.ExpressionVariables;
Expand Down Expand Up @@ -68,40 +77,70 @@ public CustomFunctions(FunctionLibraryType library, ExpressionFactory expression
this.task = task;
}

public Object execute(String functionName, Map<String, Object> params) throws ExpressionEvaluationException {
public <V extends PrismValue, D extends ItemDefinition> Object execute(String functionName, Map<String, Object> params) throws ExpressionEvaluationException {
Validate.notNull(functionName, "Function name must be specified");

List<ExpressionType> functions = library.getFunction().stream().filter(expression -> functionName.equals(expression.getName())).collect(Collectors.toList());

LOGGER.trace("functions {}", functions);
ExpressionType expression = functions.iterator().next();
ExpressionType expressionType = functions.iterator().next();

LOGGER.trace("function to execute {}", expression);
LOGGER.trace("function to execute {}", expressionType);

try {
ExpressionVariables variables = new ExpressionVariables();
if (MapUtils.isNotEmpty(params)) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
variables.addVariableDefinition(new QName(entry.getKey()), convertInput(entry, expression));
variables.addVariableDefinition(new QName(entry.getKey()), convertInput(entry, expressionType));
};
}

QName returnType = expression.getReturnType();
QName returnType = expressionType.getReturnType();
if (returnType == null) {
returnType = DOMUtil.XSD_STRING;
}

ItemDefinition outputDefinition = prismContext.getSchemaRegistry().findItemDefinitionByType(returnType);
D outputDefinition = (D) prismContext.getSchemaRegistry().findItemDefinitionByType(returnType);
if (outputDefinition == null) {
outputDefinition = new PrismPropertyDefinitionImpl<>(SchemaConstantsGenerated.C_VALUE, returnType, prismContext);
outputDefinition = (D) new PrismPropertyDefinitionImpl(SchemaConstantsGenerated.C_VALUE, returnType, prismContext);
}
if (expression.getReturnMultiplicity() != null && expression.getReturnMultiplicity() == ExpressionReturnMultiplicityType.MULTI) {
if (expressionType.getReturnMultiplicity() != null && expressionType.getReturnMultiplicity() == ExpressionReturnMultiplicityType.MULTI) {
outputDefinition.setMaxOccurs(-1);
} else {
outputDefinition.setMaxOccurs(1);
}
String shortDesc = "custom function execute";
Expression<V, D> expression = expressionFactory.makeExpression(expressionType, outputDefinition,
shortDesc, task, result);

ExpressionEvaluationContext context = new ExpressionEvaluationContext(null, variables, shortDesc, task,
result);
PrismValueDeltaSetTriple<V> outputTriple = expression.evaluate(context);

LOGGER.trace("Result of the expression evaluation: {}", outputTriple);

if (outputTriple == null) {
return null;
}

Collection<V> nonNegativeValues = outputTriple.getNonNegativeValues();

if (nonNegativeValues == null || nonNegativeValues.isEmpty()) {
return null;
}

if (outputDefinition.isMultiValue()) {
return PrismValue.getRealValuesOfCollection(nonNegativeValues);
}


if (nonNegativeValues.size() > 1) {
throw new ExpressionEvaluationException("Expression returned more than one value ("
+ nonNegativeValues.size() + ") in " + shortDesc);
}

return nonNegativeValues.iterator().next().getRealValue();

return ExpressionUtil.evaluateExpression(variables, outputDefinition, expression, expressionFactory, "description", task, result);

} catch (SchemaException | ExpressionEvaluationException | ObjectNotFoundException | CommunicationException | ConfigurationException | SecurityViolationException e) {
throw new ExpressionEvaluationException(e.getMessage(), e);
Expand All @@ -112,19 +151,27 @@ public Object execute(String functionName, Map<String, Object> params) throws Ex
private Object convertInput(Map.Entry<String, Object> entry, ExpressionType expression) throws SchemaException {

ExpressionParameterType expressionParam = expression.getParameter().stream().filter(param -> param.getName().equals(entry.getKey())).findAny().orElseThrow(SchemaException :: new);
Class<?> expressioNParameterClass = XsdTypeMapper.toJavaTypeIfKnown(expressionParam.getType());

// FIXME: awful hack
if (String.class.equals(expressioNParameterClass) && entry.getValue() instanceof PolyString) {
return ((PolyString) entry.getValue()).getOrig();
QName paramType = expressionParam.getType();
Class<?> expressionParameterClass = prismContext.getSchemaRegistry().determineClassForType(paramType);

if (expressionParameterClass != null && !DOMUtil.XSD_ANYTYPE.equals(paramType) && XmlTypeConverter.canConvert(expressionParameterClass)) {
return ExpressionUtil.convertValue(expressionParameterClass, null, entry.getValue(), prismContext.getDefaultProtector(), prismContext);
}

return entry.getValue();

// FIXME: awful hack
// if (String.class.equals(expressioNParameterClass) && entry.getValue() instanceof PolyString) {
// return ((PolyString) entry.getValue()).getOrig();
// }

//if (expressioNParameterClass != null && !expressioNParameterClass.isAssignableFrom(entry.getValue().getClass())) {
// if (expressioNParameterClass != null && !expressioNParameterClass.equals(entry.getValue().getClass())){
// throw new SchemaException("Unexpected type of value, expecting " + expressioNParameterClass.getSimpleName() + " but the actual value is " + entry.getValue().getClass().getSimpleName());
// }

return entry.getValue();
// return entry.getValue();

}

Expand Down
Expand Up @@ -149,9 +149,10 @@
map.put("country", locality)
fixedDrink = myLib.execute("addCountry", map)
}

log.info("drink: "+fixedDrink)
return fixedDrink
return fixedDrink.toString()
</code>
</script>
</expression>
Expand Down
22 changes: 22 additions & 0 deletions model/report-impl/pom.xml
Expand Up @@ -227,6 +227,12 @@
<version>3.7-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.evolveum.midpoint.repo</groupId>
<artifactId>security-enforcer-impl</artifactId>
<version>3.7-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.evolveum.midpoint.model</groupId>
<artifactId>model-test</artifactId>
Expand Down Expand Up @@ -278,6 +284,22 @@
<version>3.7-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.evolveum.midpoint.repo</groupId>
<artifactId>repo-sql-impl-test</artifactId>
<version>3.7-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency> <!-- needed as runtime dependency otherwise spring won't start -->
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<scope>test</scope>
</dependency>
<dependency> <!-- needed as runtime dependency otherwise spring won't start -->
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
Expand Down

0 comments on commit 930048c

Please sign in to comment.