diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java index 2c7f5872782..6bd8eb40cc4 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/DeltaConvertor.java @@ -102,7 +102,9 @@ public static ObjectDelta createObjectDelta(ObjectDelt ObjectType objectToAddElement = objectDeltaType.getObjectToAdd(); // PrismObject objectToAdd = prismContext.getXnodeProcessor().parseObject(objectToAddElement.getXnode()); // PrismObject objectToAdd = prismContext.getJaxbDomHack().parseObjectFromJaxb(objectToAddElement); - objectDelta.setObjectToAdd(objectToAddElement.asPrismObject()); + if (objectToAddElement != null) { + objectDelta.setObjectToAdd(objectToAddElement.asPrismObject()); + } return objectDelta; } else if (objectDeltaType.getChangeType() == ChangeTypeType.MODIFY) { ObjectDelta objectDelta = new ObjectDelta(type, ChangeType.MODIFY, prismContext); diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd index a4ee90f91b3..938f43a2412 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd @@ -6513,6 +6513,9 @@ For explicitness, only one of approverRef(s)/approverExpression(s), approvalSchema and approvalProcess should be specified.

+

+ THIS PROPERTY (approvalProcess) IS NOT SUPPORTED YET. +

@@ -10027,6 +10030,7 @@ Order in which the change processor should be invoked. (Unspecified means "at the end".) + NOT IMPLEMENTED YET. @@ -10111,8 +10115,9 @@ - - + + + @@ -10132,6 +10137,12 @@ They take all the approver information directly from the object (role or resource) being assigned. However, there are some others (namely, role/resource/user/whatever add/modify aspects) that need the explicit information about approver(s) in order to know where to route the request. + + For the former aspects, the approver information specified here takes precedence over + approver information derived from the objects being used (e.g. role or resource). + More specifically, if any approver information is here, no approver information is + taken from the objects. This could be changed (e.g. by allowing to tune this behavior) + in the future. @@ -10180,6 +10191,8 @@ For explicitness, only one of approverRef(s)/approverExpression(s), approvalSchema and approvalProcess should be specified. + + THIS PROPERTY (approvalProcess) IS NOT SUPPORTED YET. diff --git a/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd b/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd index 0b0be9a7456..114d2fa4c9f 100644 --- a/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd @@ -417,4 +417,45 @@ + + + + TODO + + + + + + + + + Object to be added + 100 + read + + + + + + + Requester's comment + 110 + read + + + + + + + Your comment + 120 + + + + + + + + + diff --git a/infra/test-util/src/main/java/com/evolveum/midpoint/test/ldap/OpenDJController.java b/infra/test-util/src/main/java/com/evolveum/midpoint/test/ldap/OpenDJController.java index 3837305499a..07ffb26f9e5 100755 --- a/infra/test-util/src/main/java/com/evolveum/midpoint/test/ldap/OpenDJController.java +++ b/infra/test-util/src/main/java/com/evolveum/midpoint/test/ldap/OpenDJController.java @@ -236,6 +236,7 @@ private void extractTemplate(File dst, String templateName) throws IOException, } templateRoot = new File(DATA_TEMPLATE_DIR, templateName); + String templateRootPath = DATA_TEMPLATE_DIR + "/" + templateName; // templateRoot.getPath does not work on Windows, as it puts "\" into the path name (leading to problems with getSystemResource) // Determing if we need to extract from JAR or directory if (templateRoot.isDirectory()) { @@ -244,7 +245,6 @@ private void extractTemplate(File dst, String templateName) throws IOException, return; } - String templateRootPath = templateRoot.getPath(); LOGGER.debug("Try to localize OpenDJ Template in JARs as " + templateRootPath); URL srcUrl = ClassLoader.getSystemResource(templateRootPath); diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/ModelContext.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/ModelContext.java index ae0146a9a8c..121e3b3f017 100644 --- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/ModelContext.java +++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/context/ModelContext.java @@ -21,9 +21,11 @@ import com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator; import com.evolveum.midpoint.model.api.ProgressInformation; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.DeltaSetTriple; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; /** * @author semancik @@ -46,4 +48,6 @@ public interface ModelContext extends Serializable, DebugD DeltaSetTriple getEvaluatedAssignmentTriple(); PrismContext getPrismContext(); // use with care + + PrismObject getSystemConfiguration(); // beware, may be null - use only as a performance optimization } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java index bc2210b2b08..795fbe92891 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java @@ -99,7 +99,7 @@ private void processEvent(WorkflowEvent event, OperationResult result) { notificationManager.processEvent(event); } catch (RuntimeException e) { result.recordFatalError("An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e); - LoggingUtils.logException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e); + LoggingUtils.logUnexpectedException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e); } // todo work correctly with operationResult (in whole notification module) @@ -113,7 +113,7 @@ private void processEvent(WorkflowEvent event) { try { notificationManager.processEvent(event); } catch (RuntimeException e) { - LoggingUtils.logException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e); + LoggingUtils.logUnexpectedException(LOGGER, "An unexpected exception occurred when preparing and sending notifications: " + e.getMessage(), e); } } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfConfiguration.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfConfiguration.java index b36296b7509..a655db0fb5a 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfConfiguration.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfConfiguration.java @@ -24,6 +24,7 @@ import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.wf.impl.processors.BaseChangeProcessor; import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; import org.apache.commons.configuration.Configuration; @@ -53,7 +54,7 @@ public class WfConfiguration implements BeanFactoryAware { private static final transient Trace LOGGER = TraceManager.getTrace(WfConfiguration.class); private static final String WF_CONFIG_SECTION = "midpoint.workflow"; - private static final String CHANGE_PROCESSORS_SECTION = "changeProcessors"; + private static final String CHANGE_PROCESSORS_SECTION = "changeProcessors"; // deprecated public static final String KEY_ENABLED = "enabled"; public static final String KEY_JDBC_DRIVER = "jdbcDriver"; @@ -68,9 +69,11 @@ public class WfConfiguration implements BeanFactoryAware { public static final List KNOWN_KEYS = Arrays.asList("midpoint.home", KEY_ENABLED, KEY_JDBC_DRIVER, KEY_JDBC_URL, KEY_JDBC_USERNAME, KEY_JDBC_PASSWORD, KEY_DATA_SOURCE, KEY_ACTIVITI_SCHEMA_UPDATE, KEY_PROCESS_CHECK_INTERVAL, - KEY_AUTO_DEPLOYMENT_FROM, KEY_ALLOW_APPROVE_OTHERS_ITEMS, CHANGE_PROCESSORS_SECTION); + KEY_AUTO_DEPLOYMENT_FROM, KEY_ALLOW_APPROVE_OTHERS_ITEMS); - @Autowired(required = true) + public static final List DEPRECATED_KEYS = Arrays.asList(CHANGE_PROCESSORS_SECTION); + + @Autowired private MidpointConfiguration midpointConfiguration; private BeanFactory beanFactory; @@ -95,7 +98,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { private boolean allowApproveOthersItems; - private List changeProcessors = null; + private List changeProcessors = new ArrayList<>(); private int processCheckInterval; private String[] autoDeploymentFrom; @@ -105,7 +108,7 @@ void initialize() { Configuration c = midpointConfiguration.getConfiguration(WF_CONFIG_SECTION); - checkAllowedKeys(c, KNOWN_KEYS); + checkAllowedKeys(c, KNOWN_KEYS, DEPRECATED_KEYS); enabled = c.getBoolean(KEY_ENABLED, true); if (!enabled) { @@ -180,8 +183,9 @@ void initialize() { validate(); } - public void checkAllowedKeys(Configuration c, List knownKeys) { - Set knownKeysSet = new HashSet(knownKeys); + public void checkAllowedKeys(Configuration c, List knownKeys, List deprecatedKeys) { + Set knownKeysSet = new HashSet<>(knownKeys); + Set deprecatedKeysSet = new HashSet<>(deprecatedKeys); Iterator keyIterator = c.getKeys(); while (keyIterator.hasNext()) { @@ -192,6 +196,9 @@ public void checkAllowedKeys(Configuration c, List knownKeys) { if (colon != -1) { normalizedKeyName = normalizedKeyName.substring(colon + 1); } + if (deprecatedKeysSet.contains(keyName) || deprecatedKeysSet.contains(normalizedKeyName)) { + throw new SystemException("Deprecated key " + keyName + " in workflow configuration. Please see https://wiki.evolveum.com/display/midPoint/Workflow+configuration."); + } if (!knownKeysSet.contains(keyName) && !knownKeysSet.contains(normalizedKeyName)) { // ...we need to test both because of keys like 'midpoint.home' throw new SystemException("Unknown key " + keyName + " in workflow configuration"); } @@ -267,46 +274,8 @@ public boolean isAllowApproveOthersItems() { return allowApproveOthersItems; } - public synchronized List getChangeProcessors() { - if (changeProcessors != null) { - return changeProcessors; - } - - changeProcessors = new ArrayList(); - - if (!enabled) { - return changeProcessors; - } - - List changeProcessorNames = new ArrayList(); // list - to preserve order - - Iterator cpIterator = getChangeProcessorsConfig().getKeys(); // returns 'processor-name' but also 'other-processor-name.aspect-name' etc. - while (cpIterator.hasNext()) { - String keyName = cpIterator.next(); - String processorName = StringUtils.substringBefore(keyName, "."); - if (!changeProcessorNames.contains(processorName)) { - changeProcessorNames.add(processorName); - } - } - - LOGGER.trace("Resolving change processors: {}", changeProcessorNames); - - for (String processorName : changeProcessorNames) { - LOGGER.trace("Searching for change processor {}", processorName); - try { - ChangeProcessor processor = (ChangeProcessor) beanFactory.getBean(processorName); - changeProcessors.add(processor); - } catch(BeansException e) { - throw new SystemException("Change processor " + processorName + " could not be found.", e); - } - } - - LOGGER.debug("Resolved " + changeProcessors.size() + " change processors."); - return changeProcessors; - } - public ChangeProcessor findChangeProcessor(String processorClassName) { - for (ChangeProcessor cp : getChangeProcessors()) { + for (ChangeProcessor cp : changeProcessors) { if (processorClassName.equals(cp.getClass().getName())) { return cp; } @@ -314,4 +283,12 @@ public ChangeProcessor findChangeProcessor(String processorClassName) { throw new IllegalStateException("Change processor " + processorClassName + " is not registered."); } + + public void registerProcessor(ChangeProcessor changeProcessor) { + changeProcessors.add(changeProcessor); + } + + public List getChangeProcessors() { + return changeProcessors; + } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfHook.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfHook.java index 29890572dff..3d432d95151 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfHook.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/WfHook.java @@ -30,8 +30,11 @@ import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.wf.impl.processors.BaseConfigurationHelper; import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -57,6 +60,9 @@ public class WfHook implements ChangeHook { @Autowired private WfConfiguration wfConfiguration; + @Autowired + private BaseConfigurationHelper baseConfigurationHelper; + @Autowired private HookRegistry hookRegistry; @@ -84,11 +90,30 @@ public HookOperationMode invoke(ModelContext context, Task task, OperationResult result.addParam("taskFromModel", task.toString()); result.addContext("model state", context.getState()); + WfConfigurationType wfConfigurationType = baseConfigurationHelper.getWorkflowConfiguration(context, result); + if (wfConfigurationType == null) { // should not occur, but ... (e.g. when initially loading objects into repository; if done in non-raw mode) + LOGGER.warn("No system configuration. Workflow approvals are disabled. Proceeding with operation execution as if everything is approved."); + result.recordSuccess(); + return HookOperationMode.FOREGROUND; + } + if (Boolean.FALSE.equals(wfConfigurationType.isModelHookEnabled())) { + LOGGER.info("Workflow model hook is disabled. Proceeding with operation execution as if everything is approved."); + result.recordSuccess(); + return HookOperationMode.FOREGROUND; + } + logOperationInformation(context); - HookOperationMode retval = processModelInvocation(context, task, result); - result.recordSuccessIfUnknown(); - return retval; + try { + HookOperationMode retval = processModelInvocation(context, wfConfigurationType, task, result); + result.recordSuccessIfUnknown(); + return retval; + } catch (RuntimeException e) { + if (result.isUnknown()) { + result.recordFatalError("Couldn't process model invocation in workflow module: " + e.getMessage(), e); + } + throw e; + } } @Override @@ -123,7 +148,7 @@ private void logOperationInformation(ModelContext context) { } } - HookOperationMode processModelInvocation(ModelContext context, Task taskFromModel, OperationResult result) { + HookOperationMode processModelInvocation(ModelContext context, WfConfigurationType wfConfigurationType, Task taskFromModel, OperationResult result) { try { @@ -133,12 +158,8 @@ HookOperationMode processModelInvocation(ModelContext context, Task taskFromMode if (LOGGER.isTraceEnabled()) { LOGGER.trace("Trying change processor: " + changeProcessor.getClass().getName()); } - if (!changeProcessor.isEnabled()) { - LOGGER.trace("It is disabled, continuing with next one."); - continue; - } try { - HookOperationMode hookOperationMode = changeProcessor.processModelInvocation(context, taskFromModel, result); + HookOperationMode hookOperationMode = changeProcessor.processModelInvocation(context, wfConfigurationType, taskFromModel, result); if (hookOperationMode != null) { return hookOperationMode; } @@ -168,5 +189,4 @@ HookOperationMode processModelInvocation(ModelContext context, Task taskFromMode return HookOperationMode.FOREGROUND; } - } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java index 8e2378abd5b..7494644db04 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java @@ -243,7 +243,7 @@ public void setPrimaryChangeAspect(Task task, PrimaryChangeAspect aspect) throws task.setExtensionProperty(w); } - public PrimaryChangeAspect getPrimaryChangeAspect(Task task, List aspects) { + public PrimaryChangeAspect getPrimaryChangeAspect(Task task, Collection aspects) { String aspectClassName = getExtensionValue(String.class, task, PcpTaskExtensionItemsNames.WFPRIMARY_CHANGE_ASPECT_NAME); if (aspectClassName == null) { throw new IllegalStateException("No wf primary change aspect defined in task " + task); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalRequestImpl.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalRequestImpl.java index d12583e2e78..e25c41c35b1 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalRequestImpl.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalRequestImpl.java @@ -40,11 +40,32 @@ public class ApprovalRequestImpl implements ApprovalRequ private ApprovalSchema approvalSchema; - public ApprovalRequestImpl(I itemToApprove, ApprovalSchemaType approvalSchema, List approverRef, List approverExpression, ExpressionType automaticallyApproved, PrismContext prismContext) { - + private ApprovalRequestImpl(I itemToApprove, PrismContext prismContext) { setPrismContext(prismContext); setItemToApprove(itemToApprove); - setApprovalSchema(new ApprovalSchemaImpl(approvalSchema, approverRef, approverExpression, automaticallyApproved, prismContext)); + } + + public ApprovalRequestImpl(I itemToApprove, PcpAspectConfigurationType config, PrismContext prismContext) { + this(itemToApprove, prismContext); + if (config != null) { + setApprovalSchema(new ApprovalSchemaImpl(config.getApprovalSchema(), config.getApproverRef(), + config.getApproverExpression(), config.getAutomaticallyApproved(), prismContext)); + } + } + + public ApprovalRequestImpl(I itemToApprove, PcpAspectConfigurationType config, ApprovalSchemaType approvalSchema, List approverRef, List approverExpression, ExpressionType automaticallyApproved, PrismContext prismContext) { + this(itemToApprove, prismContext); + if (config != null && + (!config.getApproverRef().isEmpty() || + config.getApprovalSchema() != null || + !config.getApproverExpression().isEmpty() || + config.getAutomaticallyApproved() != null)) { + setApprovalSchema(new ApprovalSchemaImpl(config.getApprovalSchema(), config.getApproverRef(), + config.getApproverExpression(), config.getAutomaticallyApproved(), prismContext)); + } else { + setApprovalSchema(new ApprovalSchemaImpl(approvalSchema, approverRef, + approverExpression, automaticallyApproved, prismContext)); + } } @Override diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseChangeProcessor.java index dcb63aba6db..33a26e92197 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseChangeProcessor.java @@ -58,11 +58,6 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } - @Override - public boolean isEnabled() { - return enabled; - } - public void setEnabled(boolean enabled) { this.enabled = enabled; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseConfigurationHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseConfigurationHelper.java index 7923dd2c5d8..b70c7a23e6b 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseConfigurationHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseConfigurationHelper.java @@ -17,16 +17,25 @@ package com.evolveum.midpoint.wf.impl.processors; import com.evolveum.midpoint.common.validator.Validator; +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.model.impl.util.Utils; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.impl.WfConfiguration; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import org.apache.commons.configuration.Configuration; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.w3c.dom.Element; @@ -55,40 +64,29 @@ public class BaseConfigurationHelper { @Autowired private PrismContext prismContext; - public void configureProcessor(BaseChangeProcessor changeProcessor, List locallyKnownKeys) { - - String beanName = changeProcessor.getBeanName(); + @Autowired + @Qualifier("cacheRepositoryService") + private RepositoryService repositoryService; - Validate.notNull(beanName, "Bean name was not set correctly."); + public void registerProcessor(BaseChangeProcessor changeProcessor) { + wfConfiguration.registerProcessor(changeProcessor); + } - Configuration c = wfConfiguration.getChangeProcessorsConfig().subset(beanName); - if (c.isEmpty()) { - LOGGER.info("Skipping reading configuration of " + beanName + ", as it is not on the list of change processors or is empty."); - return; + public WfConfigurationType getWorkflowConfiguration(ModelContext context, OperationResult result) { + if (context != null && context.getSystemConfiguration() != null) { + SystemConfigurationType systemConfigurationType = context.getSystemConfiguration().asObjectable(); + return systemConfigurationType.getWorkflowConfiguration(); } - - List allKnownKeys = new ArrayList<>(KNOWN_KEYS); - if (locallyKnownKeys != null) { - allKnownKeys.addAll(locallyKnownKeys); + PrismObject systemConfigurationTypePrismObject = null; + try { + systemConfigurationTypePrismObject = Utils.getSystemConfiguration(repositoryService, result); + } catch (SchemaException e) { + throw new SystemException("Couldn't get system configuration because of schema exception - cannot continue", e); } - wfConfiguration.checkAllowedKeys(c, allKnownKeys); - - boolean enabled = c.getBoolean(KEY_ENABLED, true); - if (!enabled) { - LOGGER.info("Change processor " + beanName + " is DISABLED."); + if (systemConfigurationTypePrismObject == null) { + // this is possible e.g. when importing initial objects; warning is already issued by Utils.getSystemConfiguration method + return null; } - changeProcessor.setEnabled(enabled); - changeProcessor.setProcessorConfiguration(c); + return systemConfigurationTypePrismObject.asObjectable().getWorkflowConfiguration(); } - - public void validateElement(Element element) throws SchemaException { - OperationResult result = new OperationResult("validateElement"); - Validator validator = new Validator(prismContext); - validator.validateSchema(element, result); - result.computeStatus(); - if (!result.isSuccess()) { - throw new SchemaException(result.getMessage(), result.getCause()); - } - } - } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java index c62f1c0f872..0429d480215 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java @@ -31,6 +31,7 @@ import com.evolveum.midpoint.wf.impl.jobs.Job; import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; import com.evolveum.midpoint.wf.impl.messages.TaskEvent; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; @@ -67,9 +68,9 @@ public interface ChangeProcessor { * and arranges everything to carry out that interaction. * * @param context Model context of the operation. - * @param taskFromModel Task in context of which the operation is carried out. - * @param result Where to put information on operation execution. - * @return non-null value if it processed the request; + * @param wfConfigurationType + *@param taskFromModel Task in context of which the operation is carried out. + * @param result Where to put information on operation execution. @return non-null value if it processed the request; * BACKGROUND = the process was "caught" by the processor, and continues in background, * FOREGROUND = nothing was left on background, the model operation should continue in foreground, * ERROR = something wrong has happened, there's no point in continuing with this operation. @@ -78,7 +79,7 @@ public interface ChangeProcessor { * Actually, the FOREGROUND return value is quite unusual, because the change processor cannot * know in advance whether other processors would not want to process the invocation from the model. */ - HookOperationMode processModelInvocation(ModelContext context, Task taskFromModel, OperationResult result) throws SchemaException; + HookOperationMode processModelInvocation(ModelContext context, WfConfigurationType wfConfigurationType, Task taskFromModel, OperationResult result) throws SchemaException; /** * Handles an event from WfMS that indicates finishing of the workflow process instance. @@ -93,12 +94,6 @@ public interface ChangeProcessor { */ void onProcessEnd(ProcessEvent event, Job job, OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException; - /** - * Checks whether this change processor is enabled (typically, using the midpoint configuration file). - * @return true if enabled, false if not - */ - boolean isEnabled(); - /** * Externalizes internal state of the process instance. Typically, uninteresting (auxiliary) data elements * are thrown away, internal representation suitable for workflow processing is replaced by "clean" prism diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpConfigurationHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpConfigurationHelper.java index f2b8d64a0ab..25a22f2ef39 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpConfigurationHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpConfigurationHelper.java @@ -50,9 +50,6 @@ public class GcpConfigurationHelper { private static final Trace LOGGER = TraceManager.getTrace(GcpConfigurationHelper.class); - private static final String KEY_GENERAL_CHANGE_PROCESSOR_CONFIGURATION = "generalChangeProcessorConfiguration"; - private static final List LOCALLY_KNOWN_KEYS = Arrays.asList(KEY_GENERAL_CHANGE_PROCESSOR_CONFIGURATION); - @Autowired private BaseConfigurationHelper baseConfigurationHelper; @@ -62,51 +59,4 @@ public class GcpConfigurationHelper { @Autowired private PrismContext prismContext; - GeneralChangeProcessorConfigurationType configure(GeneralChangeProcessor generalChangeProcessor) { - baseConfigurationHelper.configureProcessor(generalChangeProcessor, LOCALLY_KNOWN_KEYS); - if (generalChangeProcessor.isEnabled()) { - return readConfiguration(generalChangeProcessor); - } else { - return null; - } - } - - private GeneralChangeProcessorConfigurationType readConfiguration(GeneralChangeProcessor generalChangeProcessor) { - String beanName = generalChangeProcessor.getBeanName(); - - String path = determineConfigurationPath(generalChangeProcessor); - LOGGER.info("Configuration path: " + path); - - Document midpointConfig = midpointConfiguration.getXmlConfigAsDocument(); - Validate.notNull(midpointConfig, "XML version of midPoint configuration couldn't be found"); - - XPath xpath = XPathFactory.newInstance().newXPath(); - try { - Element processorConfig = (Element) xpath.evaluate(path + "/*[local-name()='" + KEY_GENERAL_CHANGE_PROCESSOR_CONFIGURATION + "']", midpointConfig, XPathConstants.NODE); - if (processorConfig == null) { - throw new SystemException("There's no " + KEY_GENERAL_CHANGE_PROCESSOR_CONFIGURATION + " element in " + beanName + " configuration."); - } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("processor configuration = {}", DOMUtil.printDom(processorConfig)); - } - try { - baseConfigurationHelper.validateElement(processorConfig); - } catch (SchemaException e) { - throw new SystemException("Schema validation failed for " + KEY_GENERAL_CHANGE_PROCESSOR_CONFIGURATION + " element in " + beanName + " configuration: " + e.getMessage(), e); - } - return prismContext.parseAnyValue(processorConfig); - } catch (XPathExpressionException|SchemaException e) { - throw new SystemException("Couldn't read general workflow processor configuration in " + beanName, e); - } - } - - // if this would not work, use simply "/configuration/midpoint/workflow/changeProcessors/generalChangeProcessor/" :) - private String determineConfigurationPath(GeneralChangeProcessor generalChangeProcessor) { - Configuration c = generalChangeProcessor.getProcessorConfiguration(); - if (!(c instanceof SubsetConfiguration)) { - throw new IllegalStateException(generalChangeProcessor.getBeanName() + " configuration is not a subset configuration, it is " + c.getClass()); - } - SubsetConfiguration sc = (SubsetConfiguration) c; - return "/*/" + sc.getPrefix().replace(".", "/"); - } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java index d34d961b764..03a35f52a11 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java @@ -28,14 +28,15 @@ import com.evolveum.midpoint.wf.impl.messages.TaskEvent; import com.evolveum.midpoint.wf.impl.processors.BaseAuditHelper; import com.evolveum.midpoint.wf.impl.processors.BaseChangeProcessor; +import com.evolveum.midpoint.wf.impl.processors.BaseConfigurationHelper; import com.evolveum.midpoint.wf.impl.processors.BaseExternalizationHelper; import com.evolveum.midpoint.wf.impl.processors.BaseModelInvocationProcessingHelper; import com.evolveum.midpoint.wf.impl.processors.general.scenarios.DefaultGcpScenarioBean; import com.evolveum.midpoint.wf.impl.processors.general.scenarios.GcpScenarioBean; -import com.evolveum.midpoint.wf.impl.util.JaxbValueContainer; import com.evolveum.midpoint.wf.impl.util.SerializationSafeContainer; import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralChangeProcessorConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralChangeProcessorScenarioType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns._public.model.model_context_3.LensContextType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; @@ -73,6 +74,9 @@ public class GeneralChangeProcessor extends BaseChangeProcessor { @Autowired private BaseExternalizationHelper baseExternalizationHelper; + @Autowired + private BaseConfigurationHelper baseConfigurationHelper; + @Autowired private BaseAuditHelper baseAuditHelper; @@ -85,30 +89,10 @@ public class GeneralChangeProcessor extends BaseChangeProcessor { @Autowired private GcpExternalizationHelper gcpExternalizationHelper; - private GeneralChangeProcessorConfigurationType processorConfigurationType; - //region Initialization and Configuration @PostConstruct public void init() { - processorConfigurationType = gcpConfigurationHelper.configure(this); - if (isEnabled()) { - // print startup message - int scenarios = processorConfigurationType.getScenario().size(); - if (scenarios > 0) { - LOGGER.info(getBeanName() + " initialized correctly (number of scenarios: " + scenarios + ")"); - } else { - LOGGER.warn(getBeanName() + " initialized correctly, but there are no scenarios - so it will never be invoked"); - } - } - } - - private GeneralChangeProcessorScenarioType findScenario(String scenarioName) { - for (GeneralChangeProcessorScenarioType scenario : processorConfigurationType.getScenario()) { - if (scenarioName.equals(scenario.getName())) { - return scenario; - } - } - throw new SystemException("Scenario named " + scenarioName + " couldn't be found"); + baseConfigurationHelper.registerProcessor(this); } private GcpScenarioBean getScenarioBean(Map variables) { @@ -131,23 +115,23 @@ private String lowerFirstChar(String name) { return Character.toLowerCase(name.charAt(0)) + name.substring(1); } - public void disableScenario(String scenarioName) { - findScenario(scenarioName).setEnabled(false); - } - - public void enableScenario(String scenarioName) { - findScenario(scenarioName).setEnabled(true); - } //endregion //region Processing model invocation @Override - public HookOperationMode processModelInvocation(ModelContext context, Task taskFromModel, OperationResult result) throws SchemaException { + public HookOperationMode processModelInvocation(ModelContext context, WfConfigurationType wfConfigurationType, Task taskFromModel, OperationResult result) throws SchemaException { + + if (wfConfigurationType.getGeneralChangeProcessor() != null && Boolean.FALSE.equals(wfConfigurationType.getGeneralChangeProcessor().isEnabled())) { + LOGGER.trace("{} is disabled", getBeanName()); + return null; + } - if (processorConfigurationType.getScenario().isEmpty()) { - LOGGER.warn("No scenarios for " + getBeanName()); + if (wfConfigurationType.getGeneralChangeProcessor() == null || wfConfigurationType.getGeneralChangeProcessor().getScenario().isEmpty()) { + LOGGER.trace("No scenarios for {}", getBeanName()); + return null; } + GeneralChangeProcessorConfigurationType processorConfigurationType = wfConfigurationType.getGeneralChangeProcessor(); for (GeneralChangeProcessorScenarioType scenarioType : processorConfigurationType.getScenario()) { GcpScenarioBean scenarioBean = findScenarioBean(scenarioType.getBeanName()); if (Boolean.FALSE.equals(scenarioType.isEnabled())) { @@ -162,7 +146,7 @@ public HookOperationMode processModelInvocation(ModelContext context, Task taskF } } LOGGER.trace("No scenario found to be applicable, exiting the change processor."); - return HookOperationMode.FOREGROUND; + return null; } private HookOperationMode applyScenario(GeneralChangeProcessorScenarioType scenarioType, GcpScenarioBean scenarioBean, ModelContext context, Task taskFromModel, OperationResult result) { diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpConfigurationHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpConfigurationHelper.java index 0dfb80c5a5a..f6a96000863 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpConfigurationHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpConfigurationHelper.java @@ -16,22 +16,15 @@ package com.evolveum.midpoint.wf.impl.processors.primary; -import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.impl.processors.BaseConfigurationHelper; -import com.evolveum.midpoint.wf.impl.processors.primary.aspect.PrimaryChangeAspect; - -import org.apache.commons.configuration.Configuration; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - /** + * Temporarily no responsibilities here. + * * @author mederly */ @Component @@ -41,38 +34,4 @@ public class PcpConfigurationHelper { @Autowired private BaseConfigurationHelper baseConfigurationHelper; - // configuration - private static final String KEY_ASPECT = "aspect"; - private static final List LOCALLY_KNOWN_KEYS = Arrays.asList(KEY_ASPECT); - - public void configure(PrimaryChangeProcessor primaryChangeProcessor) { - baseConfigurationHelper.configureProcessor(primaryChangeProcessor, LOCALLY_KNOWN_KEYS); - setPrimaryChangeProcessorAspects(primaryChangeProcessor); - } - - private void setPrimaryChangeProcessorAspects(PrimaryChangeProcessor primaryChangeProcessor) { - - List aspects = new ArrayList<>(); - - Configuration c = primaryChangeProcessor.getProcessorConfiguration(); - if (c != null) { - String[] aspectNames = c.getStringArray(KEY_ASPECT); - if (aspectNames == null || aspectNames.length == 0) { - LOGGER.warn("No aspects defined for primary change processor " + primaryChangeProcessor.getBeanName()); - } else { - for (String aspectName : aspectNames) { - LOGGER.trace("Searching for aspect " + aspectName); - try { - PrimaryChangeAspect aspect = (PrimaryChangeAspect) primaryChangeProcessor.getBeanFactory().getBean(aspectName); - aspects.add(aspect); - } catch (BeansException e) { - throw new SystemException("Change aspect " + aspectName + " could not be found.", e); - } - } - LOGGER.debug("Resolved " + aspects.size() + " process aspects for primary change processor " + primaryChangeProcessor.getBeanName()); - } - } - primaryChangeProcessor.setChangeAspects(aspects); - } - } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpJob.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpJob.java index 6d1c6dd44d9..5da446326c0 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpJob.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpJob.java @@ -22,7 +22,7 @@ public class PcpJob extends Job { } public PrimaryChangeAspect getChangeAspect() { - return getWfTaskUtil().getPrimaryChangeAspect(getTask(), getPcp().getChangeAspects()); + return getWfTaskUtil().getPrimaryChangeAspect(getTask(), getPcp().getAllChangeAspects()); } private PrimaryChangeProcessor getPcp() { diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpRepoAccessHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpRepoAccessHelper.java index 46f35c0b8de..b9ed3b865f9 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpRepoAccessHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpRepoAccessHelper.java @@ -120,10 +120,23 @@ public PrismObject getObjectAfter(Map vari return null; } - PrismObject objectAfter = objectBefore.clone(); - delta.applyTo(objectAfter); + PrismObject objectAfter; + if (delta.isAdd()) { + if (delta.getObjectToAdd() != null) { + objectAfter = delta.getObjectToAdd().clone(); + } else { + return null; + } + } else if (delta.isModify()) { + objectAfter = objectBefore.clone(); + delta.applyTo(objectAfter); + } else if (delta.isDelete()) { + return null; + } else { + return null; // should not occur + } - if (objectAfter.asObjectable() instanceof UserType) { + if (objectAfter.asObjectable() instanceof UserType) { // quite a hack miscDataUtil.resolveAssignmentTargetReferences((PrismObject) objectAfter, result); } return objectAfter; diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java index 693158b528c..a2a545702b9 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java @@ -48,32 +48,43 @@ import com.evolveum.midpoint.wf.impl.processes.ProcessInterfaceFinder; import com.evolveum.midpoint.wf.impl.processors.BaseAuditHelper; import com.evolveum.midpoint.wf.impl.processors.BaseChangeProcessor; +import com.evolveum.midpoint.wf.impl.processors.BaseConfigurationHelper; import com.evolveum.midpoint.wf.impl.processors.BaseExternalizationHelper; import com.evolveum.midpoint.wf.impl.processors.BaseModelInvocationProcessingHelper; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.PrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.xml.bind.JAXBException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; /** * @author mederly */ -public abstract class PrimaryChangeProcessor extends BaseChangeProcessor { +@Component +public class PrimaryChangeProcessor extends BaseChangeProcessor { private static final Trace LOGGER = TraceManager.getTrace(PrimaryChangeProcessor.class); @Autowired private PcpConfigurationHelper pcpConfigurationHelper; + @Autowired + private BaseConfigurationHelper baseConfigurationHelper; + @Autowired private BaseModelInvocationProcessingHelper baseModelInvocationProcessingHelper; @@ -100,7 +111,7 @@ public abstract class PrimaryChangeProcessor extends BaseChangeProcessor { public static final String UNKNOWN_OID = "?"; - List changeAspects; + Set allChangeAspects = new HashSet<>(); public enum ExecutionMode { ALL_AFTERWARDS, ALL_IMMEDIATELY, MIXED; @@ -110,11 +121,7 @@ public enum ExecutionMode { // =================================================================================== Configuration @PostConstruct public void init() { - pcpConfigurationHelper.configure(this); - } - - public void setChangeAspects(List changeAspects) { - this.changeAspects = changeAspects; + baseConfigurationHelper.registerProcessor(this); } //endregion @@ -122,7 +129,7 @@ public void setChangeAspects(List changeAspects) { // =================================================================================== Processing model invocation @Override - public HookOperationMode processModelInvocation(ModelContext context, Task taskFromModel, OperationResult result) throws SchemaException { + public HookOperationMode processModelInvocation(ModelContext context, WfConfigurationType wfConfigurationType, Task taskFromModel, OperationResult result) throws SchemaException { if (context.getState() != ModelState.PRIMARY || context.getFocusContext() == null) { return null; @@ -136,7 +143,7 @@ public HookOperationMode processModelInvocation(ModelContext context, Task taskF // examine the request using process aspects ObjectDelta changeBeingDecomposed = change.clone(); - List jobCreationInstructions = gatherStartInstructions(context, changeBeingDecomposed, taskFromModel, result); + List jobCreationInstructions = gatherStartInstructions(context, wfConfigurationType, changeBeingDecomposed, taskFromModel, result); // start the process(es) @@ -148,11 +155,26 @@ public HookOperationMode processModelInvocation(ModelContext context, Task taskF } } - private List gatherStartInstructions(ModelContext context, ObjectDelta changeBeingDecomposed, Task taskFromModel, OperationResult result) throws SchemaException { + private List gatherStartInstructions(ModelContext context, + WfConfigurationType wfConfigurationType, + ObjectDelta changeBeingDecomposed, + Task taskFromModel, OperationResult result) throws SchemaException { List startProcessInstructions = new ArrayList<>(); - for (PrimaryChangeAspect aspect : changeAspects) { - List instructions = aspect.prepareJobCreationInstructions(context, changeBeingDecomposed, taskFromModel, result); + PrimaryChangeProcessorConfigurationType processorConfigurationType = + wfConfigurationType.getPrimaryChangeProcessor(); + + if (processorConfigurationType != null && Boolean.FALSE.equals(processorConfigurationType.isEnabled())) { + LOGGER.debug("Primary change processor is disabled."); + return startProcessInstructions; + } + + for (PrimaryChangeAspect aspect : getActiveChangeAspects(processorConfigurationType)) { + if (changeBeingDecomposed.isEmpty()) { // nothing left + break; + } + List instructions = aspect.prepareJobCreationInstructions( + context, wfConfigurationType, changeBeingDecomposed, taskFromModel, result); logAspectResult(aspect, instructions); if (instructions != null) { startProcessInstructions.addAll(instructions); @@ -162,7 +184,7 @@ private List gatherStartInstructions(ModelContex // tweaking the instructions returned from aspects a bit... // if we are adding a new object, we have to set OBJECT_TO_BE_ADDED variable in all instructions - if (changeBeingDecomposed.isAdd()) { + if (changeBeingDecomposed.isAdd() && changeBeingDecomposed.getObjectToAdd() != null) { String objectToBeAdded; try { objectToBeAdded = MiscDataUtil.serializeObjectToXml(changeBeingDecomposed.getObjectToAdd()); @@ -185,6 +207,16 @@ private List gatherStartInstructions(ModelContex return startProcessInstructions; } + private Collection getActiveChangeAspects(PrimaryChangeProcessorConfigurationType processorConfigurationType) { + Collection rv = new HashSet<>(); + for (PrimaryChangeAspect aspect : getAllChangeAspects()) { + if (aspect.isEnabled(processorConfigurationType)) { + rv.add(aspect); + } + } + return rv; + } + private void logAspectResult(PrimaryChangeAspect aspect, List instructions) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Aspect " + aspect.getClass() + " returned the following process start instructions (count: " + (instructions == null ? "(null)" : instructions.size()) + "):"); @@ -250,7 +282,7 @@ private Job createRootJob(ModelContext context, ObjectDelta changeWithoutApproval, Job rootJob, ExecutionMode executionMode, OperationResult result) throws SchemaException, ObjectNotFoundException { - if (!changeWithoutApproval.isEmpty() && executionMode != ExecutionMode.ALL_AFTERWARDS) { + if (changeWithoutApproval != null && !changeWithoutApproval.isEmpty() && executionMode != ExecutionMode.ALL_AFTERWARDS) { ModelContext modelContext = contextCopyWithDeltaReplaced(context, changeWithoutApproval); JobCreationInstruction instruction0 = JobCreationInstruction.createModelOperationChildJob(rootJob, modelContext); instruction0.setTaskName("Executing changes that do not require approval"); @@ -279,7 +311,11 @@ private LensContext determineContextForRootTask(ModelContext context, ObjectDelt private LensContext contextCopyWithDeltaReplaced(ModelContext context, ObjectDelta change) throws SchemaException { LensContext contextCopy = ((LensContext) context).clone(); - contextCopy.replacePrimaryFocusDeltas(Arrays.asList(change)); + if (change != null) { + contextCopy.replacePrimaryFocusDeltas(Arrays.asList(change)); + } else { + contextCopy.replacePrimaryFocusDeltas(null); + } return contextCopy; } @@ -399,8 +435,8 @@ public AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEve //endregion //region Getters and setters - public List getChangeAspects() { - return changeAspects; + public Collection getAllChangeAspects() { + return allChangeAspects; } PrimaryChangeAspect getChangeAspect(Map variables) { @@ -414,7 +450,7 @@ public PrimaryChangeAspect findPrimaryChangeAspect(String name) { if (getBeanFactory().containsBean(name)) { return getBeanFactory().getBean(name, PrimaryChangeAspect.class); } - for (PrimaryChangeAspect w : changeAspects) { + for (PrimaryChangeAspect w : allChangeAspects) { if (name.equals(w.getClass().getName())) { return w; } @@ -422,6 +458,10 @@ public PrimaryChangeAspect findPrimaryChangeAspect(String name) { throw new IllegalStateException("Aspect " + name + " is not registered."); } + public void registerChangeAspect(PrimaryChangeAspect changeAspect) { + allChangeAspects.add(changeAspect); + } + WfTaskUtil getWfTaskUtil() { // ugly hack - used in PcpJob return wfTaskUtil; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPrepareRootOperationTaskHandler.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPrepareRootOperationTaskHandler.java index cbdd21285ab..0249884c4fd 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPrepareRootOperationTaskHandler.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/WfPrepareRootOperationTaskHandler.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.wf.impl.processors.primary; import com.evolveum.midpoint.model.impl.lens.LensContext; +import com.evolveum.midpoint.model.impl.lens.LensFocusContext; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.result.OperationResult; @@ -96,16 +97,26 @@ public TaskRunResult run(Task task) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Child job {} returned {} deltas", child, deltas.size()); } + LensFocusContext focusContext = rootContext.getFocusContext(); for (ObjectDelta delta : deltas) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Adding delta from job {} to root model context; delta = {}", child, delta.debugDump(0)); } - rootContext.getFocusContext().addPrimaryDelta(delta); + if (focusContext.getPrimaryDelta() != null && !focusContext.getPrimaryDelta().isEmpty()) { + focusContext.addPrimaryDelta(delta); + } else { + focusContext.setPrimaryDelta(delta); + } changed = true; } } } + if (rootContext.getFocusContext().getPrimaryDelta() == null || rootContext.getFocusContext().getPrimaryDelta().isEmpty()) { + rootJob.setSkipModelContextProcessingProperty(true, result); + changed = true; // regardless of whether rootContext was changed or not + } + if (changed) { rootJob.storeModelContext(rootContext); rootJob.commitChanges(result); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java index a56dbbf8868..4ee567d19ed 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java @@ -17,6 +17,7 @@ package com.evolveum.midpoint.wf.impl.processors.primary.aspect; import com.evolveum.midpoint.prism.Objectable; +import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; @@ -26,23 +27,30 @@ import com.evolveum.midpoint.wf.impl.jobs.WfTaskUtil; import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; import com.evolveum.midpoint.wf.impl.processes.ProcessInterfaceFinder; +import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalProcessInterface; +import com.evolveum.midpoint.wf.impl.processors.BaseConfigurationHelper; import com.evolveum.midpoint.wf.impl.processors.primary.PcpJob; import com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; +import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.PostConstruct; import java.util.List; import java.util.Map; /** * @author mederly */ -public abstract class BasePrimaryChangeAspect implements PrimaryChangeAspect { +public abstract class BasePrimaryChangeAspect implements PrimaryChangeAspect, BeanNameAware { private static final Trace LOGGER = TraceManager.getTrace(BasePrimaryChangeAspect.class); + private String beanName; + @Autowired protected RepositoryService repositoryService; @@ -58,6 +66,29 @@ public abstract class BasePrimaryChangeAspect implements PrimaryChangeAspect { @Autowired protected ProcessInterfaceFinder processInterfaceFinder; + @Autowired + protected BaseConfigurationHelper baseConfigurationHelper; + + @Autowired + protected PrismContext prismContext; + + @Autowired + protected ItemApprovalProcessInterface itemApprovalProcessInterface; + + @PostConstruct + public void init() { + changeProcessor.registerChangeAspect(this); + } + + @Override + public String getBeanName() { + return beanName; + } + + public void setBeanName(String name) { + this.beanName = name; + } + @Override public List> prepareDeltaOut(ProcessEvent event, PcpJob pcpJob, OperationResult result) throws SchemaException { return primaryChangeAspectHelper.prepareDeltaOut(event, pcpJob, result); @@ -76,4 +107,15 @@ public ProcessSpecificState externalizeProcessInstanceState(Map public PrimaryChangeProcessor getChangeProcessor() { return changeProcessor; } + + @Override + public boolean isEnabledByDefault() { + return false; // overriden in selected aspects + } + + @Override + public boolean isEnabled(PrimaryChangeProcessorConfigurationType processorConfigurationType) { + return primaryChangeAspectHelper.isEnabled(processorConfigurationType, this); + } + } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java index ea872d09501..1ea539a6294 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java @@ -29,6 +29,8 @@ import com.evolveum.midpoint.wf.impl.processors.primary.PcpJob; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; @@ -64,13 +66,13 @@ public interface PrimaryChangeAspect { * If yes, it takes these deltas out of the original change and prepares instruction(s) to start wf process(es). * * @param modelContext Original model context (e.g. to be able to get information about whole context of the operation) + * @param wfConfigurationType * @param change Change to be examined and modified by implementation of this method * @param taskFromModel General context of the operation - the method should not modify the task. - * @param result Operation result - the method should report any errors here (TODO what about creating subresults?) - * @return list of start process instructions + * @param result Operation result - the method should report any errors here (TODO what about creating subresults?) @return list of start process instructions * @see com.evolveum.midpoint.wf.impl.jobs.JobCreationInstruction */ - List prepareJobCreationInstructions(ModelContext modelContext, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException; + List prepareJobCreationInstructions(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException; /** * On process instance end, prepares deltaOut based in deltaIn and information gathered during approval process. @@ -138,4 +140,13 @@ public interface PrimaryChangeAspect { * @return external representation */ ProcessSpecificState externalizeProcessInstanceState(Map variables); + + /** + * Returns true if this aspect is enabled by default, i.e. even if not listed in primary change processor configuration. + */ + boolean isEnabledByDefault(); + + boolean isEnabled(PrimaryChangeProcessorConfigurationType processorConfigurationType); + + String getBeanName(); } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspectHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspectHelper.java index 02c643259a3..751b8113e1c 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspectHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspectHelper.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.api.context.ModelElementContext; +import com.evolveum.midpoint.model.api.context.ModelState; import com.evolveum.midpoint.prism.Objectable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; @@ -40,16 +41,23 @@ import com.evolveum.midpoint.wf.impl.processors.primary.PcpJob; import com.evolveum.midpoint.wf.util.ApprovalUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.GenericPcpAspectConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; +import org.apache.velocity.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.xml.namespace.QName; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; @@ -214,6 +222,79 @@ public void resolveRolesAndOrgUnits(PrismObject user, OperationResult } } } + + public boolean isEnabled(PrimaryChangeProcessorConfigurationType processorConfigurationType, PrimaryChangeAspect aspect) { + if (processorConfigurationType == null) { + return aspect.isEnabledByDefault(); + } + PcpAspectConfigurationType aspectConfigurationType = getPcpAspectConfigurationType(processorConfigurationType, aspect); // result may be null + return isEnabled(aspectConfigurationType, aspect.isEnabledByDefault()); + } + + public PcpAspectConfigurationType getPcpAspectConfigurationType(WfConfigurationType wfConfigurationType, PrimaryChangeAspect aspect) { + if (wfConfigurationType == null) { + return null; + } + return getPcpAspectConfigurationType(wfConfigurationType.getPrimaryChangeProcessor(), aspect); + } + + public PcpAspectConfigurationType getPcpAspectConfigurationType(PrimaryChangeProcessorConfigurationType processorConfigurationType, PrimaryChangeAspect aspect) { + if (processorConfigurationType == null) { + return null; + } + String aspectName = aspect.getBeanName(); + String getterName = "get" + StringUtils.capitalizeFirstLetter(aspectName); + Object aspectConfigurationObject; + try { + Method getter = processorConfigurationType.getClass().getDeclaredMethod(getterName); + try { + aspectConfigurationObject = getter.invoke(processorConfigurationType); + } catch (IllegalAccessException|InvocationTargetException e) { + throw new SystemException("Couldn't obtain configuration for aspect " + aspectName + " from the workflow configuration.", e); + } + if (aspectConfigurationObject != null) { + return (PcpAspectConfigurationType) aspectConfigurationObject; + } + LOGGER.trace("Specific configuration for {} not found, trying generic configuration", aspectName); + } catch (NoSuchMethodException e) { + // nothing wrong with this, let's try generic configuration + LOGGER.trace("Configuration getter method for {} not found, trying generic configuration", aspectName); + } + + for (GenericPcpAspectConfigurationType genericConfig : processorConfigurationType.getOtherAspect()) { + if (aspectName.equals(genericConfig.getName())) { + return genericConfig; + } + } + return null; + } + + private boolean isEnabled(PcpAspectConfigurationType configurationType, boolean enabledByDefault) { + if (configurationType == null) { + return enabledByDefault; + } else if (Boolean.FALSE.equals(configurationType.isEnabled())) { + return false; + } else { + return true; + } + } + + public boolean isUserRelated(ModelContext context) { + return isRelatedToType(context, UserType.class); + } + + public boolean isRelatedToType(ModelContext context, Class type) { + if (context.getFocusContext() == null) { + return false; + } + + ObjectDelta change = context.getFocusContext().getPrimaryDelta(); + if (change == null) { + return false; + } + + return type.isAssignableFrom(change.getObjectTypeClass()); + } //endregion } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddAbstractRoleAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddAbstractRoleAspect.java new file mode 100644 index 00000000000..c007fd62817 --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddAbstractRoleAspect.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.wf.impl.processors.primary.other; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import org.apache.commons.lang3.Validate; +import org.springframework.stereotype.Component; + +/** + * Change aspect that manages abstract role (i.e. Role or Org) addition. + * + * @author mederly + */ +@Component +public class AddAbstractRoleAspect extends AddObjectAspect { + + @Override + protected Class getObjectClass() { + return AbstractRoleType.class; + } + + @Override + protected String getObjectLabel(AbstractRoleType object) { + Validate.notNull(object); + if (object instanceof RoleType) { + return "role " + object.getName(); + } else if (object instanceof OrgType) { + return "org " + object.getName(); + } else { + // should not occur + return object.getClass().getSimpleName() + " " + object.getName(); + } + } +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddObjectAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddObjectAspect.java new file mode 100644 index 00000000000..44e2c4a9653 --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddObjectAspect.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.wf.impl.processors.primary.other; + +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismObjectDefinition; +import com.evolveum.midpoint.prism.delta.ChangeType; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest; +import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequestImpl; +import com.evolveum.midpoint.wf.impl.processes.itemApproval.ProcessVariableNames; +import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildJobCreationInstruction; +import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; +import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AddObjectApprovalFormType; +import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; +import org.apache.commons.lang.Validate; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * Change aspect that manages addition of an object. + * + * @author mederly + */ +public abstract class AddObjectAspect extends BasePrimaryChangeAspect { + + private static final Trace LOGGER = TraceManager.getTrace(AddObjectAspect.class); + + //region ------------------------------------------------------------ Things that execute on request arrival + + protected abstract Class getObjectClass(); + protected abstract String getObjectLabel(T object); + + @Override + public List prepareJobCreationInstructions(ModelContext modelContext, + WfConfigurationType wfConfigurationType, + ObjectDelta change, + Task taskFromModel, OperationResult result) throws SchemaException { + PcpAspectConfigurationType config = primaryChangeAspectHelper.getPcpAspectConfigurationType(wfConfigurationType, this); + if (config == null) { + return null; // this should not occur (because this aspect is not enabled by default), but check it just to be sure + } + if (!primaryChangeAspectHelper.isRelatedToType(modelContext, getObjectClass())) { + return null; + } + List> approvalRequestList = getApprovalRequests(modelContext, config, change, result); + if (approvalRequestList == null || approvalRequestList.isEmpty()) { + return null; + } + return prepareJobCreateInstructions(modelContext, taskFromModel, result, approvalRequestList); + } + + private List> getApprovalRequests(ModelContext modelContext, PcpAspectConfigurationType config, + ObjectDelta change, OperationResult result) { + if (change.getChangeType() != ChangeType.ADD) { + return null; + } + T objectType = (T) change.getObjectToAdd().asObjectable().clone(); + change.setObjectToAdd(null); // make the change empty + return Arrays.asList(createApprovalRequest(config, objectType)); + } + + // creates an approval request for a given role create request + private ApprovalRequest createApprovalRequest(PcpAspectConfigurationType config, T objectType) { + + return new ApprovalRequestImpl(objectType, config, prismContext); + } + + private List prepareJobCreateInstructions(ModelContext modelContext, Task taskFromModel, OperationResult result, + List> approvalRequestList) throws SchemaException { + List instructions = new ArrayList<>(); + + for (ApprovalRequest approvalRequest : approvalRequestList) { // there should be just one + + assert approvalRequest.getPrismContext() != null; + + LOGGER.trace("Approval request = {}", approvalRequest); + + T objectToAdd = approvalRequest.getItemToApprove(); + Validate.notNull(objectToAdd); + String objectLabel = getObjectLabel(objectToAdd); + + PrismObject requester = primaryChangeAspectHelper.getRequester(taskFromModel, result); + + // create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case) + PcpChildJobCreationInstruction instruction = + PcpChildJobCreationInstruction.createInstruction(getChangeProcessor()); + + // set some common task/process attributes + instruction.prepareCommonAttributes(this, modelContext, null, requester); // objectOid is null (because object does not exist yet) + + // prepare and set the delta that has to be approved + ObjectDelta delta = assignmentToDelta(modelContext); + instruction.setDeltaProcessAndTaskVariables(delta); + + // set the names of midPoint task and activiti process instance + String andExecuting = instruction.isExecuteApprovedChangeImmediately() ? "and executing " : ""; + instruction.setTaskName("Workflow for approving " + andExecuting + "creation of " + objectLabel); + instruction.setProcessInstanceName("Creating " + objectLabel); + + // setup general item approval process + String approvalTaskName = "Approve creating " + objectLabel; + itemApprovalProcessInterface.prepareStartInstruction(instruction, approvalRequest, approvalTaskName); + + instructions.add(instruction); + } + return instructions; + } + + private ObjectDelta assignmentToDelta(ModelContext modelContext) { + return modelContext.getFocusContext().getPrimaryDelta(); + } + + //endregion + + //region ------------------------------------------------------------ Things that execute when item is being approved + + @Override + public PrismObject prepareQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("getRequestSpecific starting: execution id {}, pid {}, variables = {}", task.getExecutionId(), task.getProcessInstanceId(), variables); + } + + PrismObjectDefinition formDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(AddObjectApprovalFormType.COMPLEX_TYPE); + PrismObject formPrism = formDefinition.instantiate(); + AddObjectApprovalFormType form = formPrism.asObjectable(); + + ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); + request.setPrismContext(prismContext); + Validate.notNull(request, "Approval request is not present among process variables"); + form.setObjectToAdd(getObjectLabel(request.getItemToApprove())); + + form.setRequesterComment(null); // TODO + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Resulting prism object instance = {}", formPrism.debugDump()); + } + return formPrism; + } + + @Override + public PrismObject prepareRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { + + ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); + request.setPrismContext(prismContext); + Validate.notNull(request, "Approval request is not present among process variables"); + return request.getItemToApprove().asPrismObject(); + } + + //endregion +} \ No newline at end of file diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddResourceAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddResourceAspect.java new file mode 100644 index 00000000000..2ae58222a6a --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddResourceAspect.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.wf.impl.processors.primary.other; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; +import org.apache.commons.lang3.Validate; +import org.springframework.stereotype.Component; + +/** + * Change aspect that manages resource addition. + * + * @author mederly + */ +@Component +public class AddResourceAspect extends AddObjectAspect { + + @Override + protected Class getObjectClass() { + return ResourceType.class; + } + + @Override + protected String getObjectLabel(ResourceType object) { + Validate.notNull(object); + return "resource " + object.getName(); + } +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddUserAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddUserAspect.java new file mode 100644 index 00000000000..cba26fccf2d --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/AddUserAspect.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.wf.impl.processors.primary.other; + +import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import org.apache.commons.lang3.Validate; +import org.springframework.stereotype.Component; + +/** + * Change aspect that manages user addition. + * + * @author mederly + */ +@Component +public class AddUserAspect extends AddObjectAspect { + + @Override + protected Class getObjectClass() { + return UserType.class; + } + + @Override + protected String getObjectLabel(UserType object) { + Validate.notNull(object); + return "user " + object.getName(); + } +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddResourceAssignmentAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddResourceAssignmentAspect.java index b45fc1a6101..a121454233e 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddResourceAssignmentAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddResourceAssignmentAspect.java @@ -43,22 +43,20 @@ import com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AbstractRoleAssignmentApprovalFormType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.ResourceAssignmentApprovalFormType; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.xml.datatype.XMLGregorianCalendar; -import java.text.DateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -81,29 +79,39 @@ public class AddResourceAssignmentAspect extends BasePrimaryChangeAspect { @Autowired private ItemApprovalProcessInterface itemApprovalProcessInterface; + @Override + public boolean isEnabledByDefault() { + return true; + } + //region ------------------------------------------------------------ Things that execute on request arrival @Override - public List prepareJobCreationInstructions(ModelContext modelContext, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { + public List prepareJobCreationInstructions(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { - List> approvalRequestList = getApprovalRequests(modelContext, change, result); + if (!primaryChangeAspectHelper.isUserRelated(modelContext)) { + return null; + } + List> approvalRequestList = getApprovalRequests(modelContext, wfConfigurationType, change, result); if (approvalRequestList == null || approvalRequestList.isEmpty()) { return null; } return prepareJobCreateInstructions(modelContext, taskFromModel, result, approvalRequestList); } - private List> getApprovalRequests(ModelContext modelContext, ObjectDelta change, OperationResult result) { + private List> getApprovalRequests(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, OperationResult result) { if (change.getChangeType() == ChangeType.ADD) { - return getApprovalRequestsFromUserAdd(change, result); + return getApprovalRequestsFromUserAdd(wfConfigurationType, change, result); } else if (change.getChangeType() == ChangeType.MODIFY) { - return getApprovalRequestsFromUserModify(modelContext.getFocusContext().getObjectOld(), change, result); + return getApprovalRequestsFromUserModify(wfConfigurationType, modelContext.getFocusContext().getObjectOld(), change, result); } return null; } // we look for assignments of resources that should be approved - private List> getApprovalRequestsFromUserAdd(ObjectDelta change, OperationResult result) { + private List> getApprovalRequestsFromUserAdd(WfConfigurationType wfConfigurationType, + ObjectDelta change, + OperationResult result) { List> approvalRequestList = new ArrayList<>(); UserType user = (UserType) change.getObjectToAdd().asObjectable(); @@ -130,7 +138,7 @@ private List> getApprovalRequestsFromUserAdd(Obj continue; } AssignmentType assignmentClone = cloneAndCanonicalizeAssignment(assignmentType); - approvalRequestList.add(createApprovalRequest(assignmentClone, resourceType)); + approvalRequestList.add(createApprovalRequest(wfConfigurationType, assignmentClone, resourceType)); assignmentTypeIterator.remove(); } return approvalRequestList; @@ -149,7 +157,10 @@ private AssignmentType cloneAndCanonicalizeAssignment(AssignmentType assignmentT return assignmentClone; } - private List> getApprovalRequestsFromUserModify(PrismObject userOld, ObjectDelta change, OperationResult result) { + private List> getApprovalRequestsFromUserModify(WfConfigurationType wfConfigurationType, + PrismObject userOld, + ObjectDelta change, + OperationResult result) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("Resource-related assignments in user modify delta: "); @@ -173,7 +184,7 @@ private List> getApprovalRequestsFromUserModify( if (LOGGER.isTraceEnabled()) { LOGGER.trace("Assignment to add = {}", assignmentValue.debugDump()); } - ApprovalRequest req = processAssignmentToAdd(assignmentValue, result); + ApprovalRequest req = processAssignmentToAdd(wfConfigurationType, assignmentValue, result); if (req != null) { approvalRequestList.add(req); valueIterator.remove(); @@ -190,7 +201,7 @@ private List> getApprovalRequestsFromUserModify( if (existsEquivalentValue(userOld, assignmentValue)) { continue; } - ApprovalRequest req = processAssignmentToAdd(assignmentValue, result); + ApprovalRequest req = processAssignmentToAdd(wfConfigurationType, assignmentValue, result); if (req != null) { approvalRequestList.add(req); valueIterator.remove(); @@ -218,7 +229,7 @@ private boolean existsEquivalentValue(PrismObject userOld, return false; } - private ApprovalRequest processAssignmentToAdd(PrismContainerValue assignmentCVal, OperationResult result) { + private ApprovalRequest processAssignmentToAdd(WfConfigurationType wfConfigurationType, PrismContainerValue assignmentCVal, OperationResult result) { if (assignmentCVal == null) { return null; } @@ -240,13 +251,15 @@ private ApprovalRequest processAssignmentToAdd(PrismContainerVal } AssignmentType assignmentClone = assignmentType.clone(); PrismContainerValue.copyDefinition(assignmentClone, assignmentType); - return createApprovalRequest(assignmentClone, resourceType); + return createApprovalRequest(wfConfigurationType, assignmentClone, resourceType); } // creates an approval request for a given resource assignment // @pre there are approvers defined - private ApprovalRequest createApprovalRequest(AssignmentType a, ResourceType resourceType) { - return new ApprovalRequestImpl(a, null, resourceType.getBusiness().getApproverRef(), null, null, prismContext); + private ApprovalRequest createApprovalRequest(WfConfigurationType wfConfigurationType, AssignmentType a, ResourceType resourceType) { + PcpAspectConfigurationType config = primaryChangeAspectHelper.getPcpAspectConfigurationType( + wfConfigurationType, this); + return new ApprovalRequestImpl(a, config, null, resourceType.getBusiness().getApproverRef(), null, null, prismContext); } // @pre there is a construction with a resource ref diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddRoleAssignmentAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddRoleAssignmentAspect.java index 4b5c1a38c69..f4d695d57cf 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddRoleAssignmentAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/AddRoleAssignmentAspect.java @@ -47,8 +47,9 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AbstractRoleAssignmentApprovalFormType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; @@ -90,29 +91,37 @@ public class AddRoleAssignmentAspect extends BasePrimaryChangeAspect { @Autowired private ItemApprovalProcessInterface itemApprovalProcessInterface; + @Override + public boolean isEnabledByDefault() { + return true; + } + //region ------------------------------------------------------------ Things that execute on request arrival @Override - public List prepareJobCreationInstructions(ModelContext modelContext, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { + public List prepareJobCreationInstructions(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { - List> approvalRequestList = getApprovalRequests(modelContext, change, result); + if (!primaryChangeAspectHelper.isUserRelated(modelContext)) { + return null; + } + List> approvalRequestList = getApprovalRequests(modelContext, wfConfigurationType, change, result); if (approvalRequestList == null || approvalRequestList.isEmpty()) { return null; } return prepareJobCreateInstructions(modelContext, taskFromModel, result, approvalRequestList); } - private List> getApprovalRequests(ModelContext modelContext, ObjectDelta change, OperationResult result) { + private List> getApprovalRequests(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, OperationResult result) { if (change.getChangeType() == ChangeType.ADD) { - return getApprovalRequestsFromUserAdd(change, result); + return getApprovalRequestsFromUserAdd(wfConfigurationType, change, result); } else if (change.getChangeType() == ChangeType.MODIFY) { - return getApprovalRequestsFromUserModify(modelContext.getFocusContext().getObjectOld(), change, result); + return getApprovalRequestsFromUserModify(wfConfigurationType, modelContext.getFocusContext().getObjectOld(), change, result); } return null; } // we look for assignments of roles that should be approved - private List> getApprovalRequestsFromUserAdd(ObjectDelta change, OperationResult result) { + private List> getApprovalRequestsFromUserAdd(WfConfigurationType wfConfigurationType, ObjectDelta change, OperationResult result) { List> approvalRequestList = new ArrayList<>(); UserType user = (UserType) change.getObjectToAdd().asObjectable(); @@ -134,7 +143,7 @@ private List> getApprovalRequestsFromUserAdd(Obj AssignmentType aCopy = a.clone(); PrismContainerValue.copyDefinition(aCopy, a); aCopy.setTarget(role); - approvalRequestList.add(createApprovalRequest(aCopy, role)); + approvalRequestList.add(createApprovalRequest(wfConfigurationType, aCopy, role)); assignmentTypeIterator.remove(); } } @@ -142,7 +151,7 @@ private List> getApprovalRequestsFromUserAdd(Obj return approvalRequestList; } - private List> getApprovalRequestsFromUserModify(PrismObject userOld, ObjectDelta change, OperationResult result) { + private List> getApprovalRequestsFromUserModify(WfConfigurationType wfConfigurationType, PrismObject userOld, ObjectDelta change, OperationResult result) { if (LOGGER.isTraceEnabled()) { LOGGER.trace("AbstractRole-related assignments in user modify delta: "); @@ -166,7 +175,7 @@ private List> getApprovalRequestsFromUserModify( if (LOGGER.isTraceEnabled()) { LOGGER.trace("Assignment to add = {}", assignmentValue.debugDump()); } - ApprovalRequest req = processAssignmentToAdd(assignmentValue, result); + ApprovalRequest req = processAssignmentToAdd(wfConfigurationType, assignmentValue, result); if (req != null) { approvalRequestList.add(req); valueIterator.remove(); @@ -183,7 +192,7 @@ private List> getApprovalRequestsFromUserModify( if (existsEquivalentValue(userOld, assignmentValue)) { continue; } - ApprovalRequest req = processAssignmentToAdd(assignmentValue, result); + ApprovalRequest req = processAssignmentToAdd(wfConfigurationType, assignmentValue, result); if (req != null) { approvalRequestList.add(req); valueIterator.remove(); @@ -211,7 +220,7 @@ private boolean existsEquivalentValue(PrismObject userOld, return false; } - private ApprovalRequest processAssignmentToAdd(PrismContainerValue o, OperationResult result) { + private ApprovalRequest processAssignmentToAdd(WfConfigurationType wfConfigurationType, PrismContainerValue o, OperationResult result) { PrismContainerValue at = o; ObjectType objectType = primaryChangeAspectHelper.resolveObjectRef(at.getValue(), result); if (objectType instanceof AbstractRoleType) { @@ -223,15 +232,17 @@ private ApprovalRequest processAssignmentToAdd(PrismContainerVal if (approvalRequired) { AssignmentType aCopy = at.asContainerable().clone(); PrismContainerValue.copyDefinition(aCopy, at.asContainerable()); - return createApprovalRequest(aCopy, role); + return createApprovalRequest(wfConfigurationType, aCopy, role); } } return null; } // creates an approval request for a given role assignment - private ApprovalRequest createApprovalRequest(AssignmentType a, AbstractRoleType role) { - return new ApprovalRequestImpl(a, role.getApprovalSchema(), role.getApproverRef(), role.getApproverExpression(), role.getAutomaticallyApproved(), prismContext); + private ApprovalRequest createApprovalRequest(WfConfigurationType wfConfigurationType, AssignmentType a, AbstractRoleType role) { + PcpAspectConfigurationType config = primaryChangeAspectHelper.getPcpAspectConfigurationType( + wfConfigurationType, this); + return new ApprovalRequestImpl(a, config, role.getApprovalSchema(), role.getApproverRef(), role.getApproverExpression(), role.getAutomaticallyApproved(), prismContext); } // approvalRequestList should contain de-referenced roles and approvalRequests that have prismContext set diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ChangePasswordAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ChangePasswordAspect.java index 8cb077c5d39..c1eed389728 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ChangePasswordAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ChangePasswordAspect.java @@ -42,6 +42,7 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemObjectsType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; import org.springframework.beans.factory.annotation.Autowired; @@ -76,7 +77,7 @@ public class ChangePasswordAspect extends BasePrimaryChangeAspect { private ItemApprovalProcessInterface itemApprovalProcessInterface; @Override - public List prepareJobCreationInstructions(ModelContext modelContext, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { + public List prepareJobCreationInstructions(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { List> approvalRequestList = new ArrayList>(); List instructions = new ArrayList<>(); @@ -125,7 +126,7 @@ private ApprovalRequest createApprovalRequest(ItemDelta delta) { List approvers = new ArrayList(); approvers.add(approverRef); - return new ApprovalRequestImpl("Password change", null, approvers, null, null, prismContext); + return new ApprovalRequestImpl("Password change", null, null, approvers, null, null, prismContext); } private PcpChildJobCreationInstruction createStartProcessInstruction(ModelContext modelContext, ItemDelta delta, ApprovalRequest approvalRequest, Task taskFromModel, OperationResult result) throws SchemaException { diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyResourceAssignmentAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyResourceAssignmentAspect.java index d40e590522f..912d10e856c 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyResourceAssignmentAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyResourceAssignmentAspect.java @@ -26,9 +26,7 @@ import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.path.IdItemPathSegment; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.path.ItemPathSegment; import com.evolveum.midpoint.schema.DeltaConvertor; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; @@ -42,16 +40,15 @@ import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalProcessInterface; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ProcessVariableNames; import com.evolveum.midpoint.wf.impl.processes.modifyResourceAssignment.ResourceAssignmentModification; -import com.evolveum.midpoint.wf.impl.processes.modifyRoleAssignment.AbstractRoleAssignmentModification; import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildJobCreationInstruction; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AbstractRoleAssignmentModificationApprovalFormType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.ResourceAssignmentModificationApprovalFormType; import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; @@ -85,24 +82,35 @@ public class ModifyResourceAssignmentAspect extends BasePrimaryChangeAspect { @Autowired private ItemApprovalProcessInterface itemApprovalProcessInterface; + @Override + public boolean isEnabledByDefault() { + return true; + } + //region ------------------------------------------------------------ Things that execute on request arrival @Override - public List prepareJobCreationInstructions(ModelContext modelContext, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { + public List prepareJobCreationInstructions(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { - List> approvalRequestList = getApprovalRequests(modelContext, change, result); + if (!primaryChangeAspectHelper.isUserRelated(modelContext)) { + return null; + } + List> approvalRequestList = getApprovalRequests(modelContext, wfConfigurationType, change, result); if (approvalRequestList == null || approvalRequestList.isEmpty()) { return null; } return prepareJobCreateInstructions(modelContext, taskFromModel, result, approvalRequestList); } - private List> getApprovalRequests(ModelContext modelContext, ObjectDelta change, OperationResult result) throws SchemaException { + private List> getApprovalRequests(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, OperationResult result) throws SchemaException { if (change.getChangeType() != ChangeType.MODIFY) { return null; } PrismObject userOld = (PrismObject) modelContext.getFocusContext().getObjectOld(); + PcpAspectConfigurationType config = primaryChangeAspectHelper.getPcpAspectConfigurationType( + wfConfigurationType, this); + if (LOGGER.isTraceEnabled()) { LOGGER.trace("Resource-related assignments in user modify delta: "); } @@ -145,7 +153,7 @@ private List> getApprovalRequest PrismContainerValue.copyDefinition(aCopy, assignmentType); ResourceType resourceType = primaryChangeAspectHelper.resolveResourceRef(assignmentType, result); // todo eliminate redundant fetch ResourceAssignmentModification itemToApprove = new ResourceAssignmentModification(aCopy, resourceType, entry.getValue()); - ApprovalRequest approvalRequest = new ApprovalRequestImpl(itemToApprove, null, resourceType.getBusiness().getApproverRef(), null, null, prismContext); + ApprovalRequest approvalRequest = new ApprovalRequestImpl(itemToApprove, config, null, resourceType.getBusiness().getApproverRef(), null, null, prismContext); approvalRequestList.add(approvalRequest); } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyRoleAssignmentAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyRoleAssignmentAspect.java index 51d7c570148..afa9bf8b22a 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyRoleAssignmentAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/ModifyRoleAssignmentAspect.java @@ -48,7 +48,9 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType; import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AbstractRoleAssignmentModificationApprovalFormType; import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; @@ -82,25 +84,36 @@ public class ModifyRoleAssignmentAspect extends BasePrimaryChangeAspect { @Autowired private ItemApprovalProcessInterface itemApprovalProcessInterface; + @Override + public boolean isEnabledByDefault() { + return true; + } + //region ------------------------------------------------------------ Things that execute on request arrival @Override - public List prepareJobCreationInstructions(ModelContext modelContext, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { + public List prepareJobCreationInstructions(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, Task taskFromModel, OperationResult result) throws SchemaException { - List> approvalRequestList = getApprovalRequests(modelContext, change, result); + if (!primaryChangeAspectHelper.isUserRelated(modelContext)) { + return null; + } + List> approvalRequestList = getApprovalRequests(modelContext, wfConfigurationType, change, result); if (approvalRequestList == null || approvalRequestList.isEmpty()) { return null; } return prepareJobCreateInstructions(modelContext, taskFromModel, result, approvalRequestList); } - private List> getApprovalRequests(ModelContext modelContext, ObjectDelta change, OperationResult result) throws SchemaException { + private List> getApprovalRequests(ModelContext modelContext, WfConfigurationType wfConfigurationType, ObjectDelta change, OperationResult result) throws SchemaException { if (change.getChangeType() != ChangeType.MODIFY) { return null; } PrismObject userOld = (PrismObject) modelContext.getFocusContext().getObjectOld(); UserType userTypeOld = userOld.asObjectable(); + PcpAspectConfigurationType config = primaryChangeAspectHelper.getPcpAspectConfigurationType( + wfConfigurationType, this); + if (LOGGER.isTraceEnabled()) { LOGGER.trace("Role-related assignments in user modify delta: "); } @@ -145,7 +158,7 @@ private List> getApprovalReq PrismContainerValue.copyDefinition(aCopy, assignmentType); AbstractRoleType role = (AbstractRoleType) primaryChangeAspectHelper.resolveObjectRef(assignmentType, result); AbstractRoleAssignmentModification itemToApprove = new AbstractRoleAssignmentModification(aCopy, role, entry.getValue()); - ApprovalRequest approvalRequest = new ApprovalRequestImpl(itemToApprove, role.getApprovalSchema(), role.getApproverRef(), role.getApproverExpression(), role.getAutomaticallyApproved(), prismContext); + ApprovalRequest approvalRequest = new ApprovalRequestImpl(itemToApprove, config, role.getApprovalSchema(), role.getApproverRef(), role.getApproverExpression(), role.getAutomaticallyApproved(), prismContext); approvalRequestList.add(approvalRequest); } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/PrimaryUserChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/PrimaryUserChangeProcessor.java deleted file mode 100644 index be1edbce3a3..00000000000 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/user/PrimaryUserChangeProcessor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2010-2013 Evolveum - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.evolveum.midpoint.wf.impl.processors.primary.user; - -import com.evolveum.midpoint.model.api.context.ModelContext; -import com.evolveum.midpoint.model.api.context.ModelState; -import com.evolveum.midpoint.model.api.hooks.HookOperationMode; -import com.evolveum.midpoint.prism.Objectable; -import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.logging.Trace; -import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; - -import org.springframework.stereotype.Component; - -/** - * Deals with approving primary changes related to a user. Typical such changes are adding of a role or an account. - * - * @author mederly - */ - -@Component("primaryUserChangeProcessor") -public class PrimaryUserChangeProcessor extends PrimaryChangeProcessor { - - private static final Trace LOGGER = TraceManager.getTrace(PrimaryUserChangeProcessor.class); - - @Override - public HookOperationMode processModelInvocation(ModelContext context, Task taskFromModel, OperationResult result) throws SchemaException { - - if (context.getState() != ModelState.PRIMARY || context.getFocusContext() == null) { - return null; - } - - ObjectDelta change = context.getFocusContext().getPrimaryDelta(); - if (change == null) { - return null; - } - - // let's check whether we deal with a user - - if (!UserType.class.isAssignableFrom(change.getObjectTypeClass())) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("change object type class is not a UserType (it is " + change.getObjectTypeClass() + "), exiting " + this.getClass().getSimpleName()); - } - return null; - } - - // the rest is quite generic - return super.processModelInvocation(context, taskFromModel, result); - } - - -} diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/AbstractWfTest.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/AbstractWfTest.java index a71dd4731ed..d94dc6ad4cd 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/AbstractWfTest.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/AbstractWfTest.java @@ -41,7 +41,6 @@ import com.evolveum.midpoint.prism.util.PrismTestUtil; import com.evolveum.midpoint.schema.DeltaConvertor; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskExecutionStatus; import com.evolveum.midpoint.task.api.TaskManager; @@ -178,22 +177,24 @@ public void initSystem(Task initTask, OperationResult initResult) ObjectReferenceType approver = role2.getApprovalSchema().getLevel().get(0).getApproverRef().get(0); assertEquals("Wrong OID of Role2's approver", R2BOSS_OID, approver.getOid()); - - primaryChangeProcessor.setEnabled(true); - generalChangeProcessor.setEnabled(false); } protected void checkUserApprovers(String oid, List expectedApprovers, OperationResult result) throws SchemaException, ObjectNotFoundException { PrismObject user = repositoryService.getObject(UserType.class, oid, null, result); - checkUserApprovers(user, expectedApprovers, user.asObjectable().getMetadata().getModifyApproverRef(), result); + checkApprovers(user, expectedApprovers, user.asObjectable().getMetadata().getModifyApproverRef(), result); } protected void checkUserApproversForCreate(String oid, List expectedApprovers, OperationResult result) throws SchemaException, ObjectNotFoundException { PrismObject user = repositoryService.getObject(UserType.class, oid, null, result); - checkUserApprovers(user, expectedApprovers, user.asObjectable().getMetadata().getCreateApproverRef(), result); + checkApprovers(user, expectedApprovers, user.asObjectable().getMetadata().getCreateApproverRef(), result); + } + + protected void checkApproversForCreate(Class clazz, String oid, List expectedApprovers, OperationResult result) throws SchemaException, ObjectNotFoundException { + PrismObject object = repositoryService.getObject(clazz, oid, null, result); + checkApprovers(object, expectedApprovers, object.asObjectable().getMetadata().getCreateApproverRef(), result); } - protected void checkUserApprovers(PrismObject user, List expectedApprovers, List realApprovers, OperationResult result) throws SchemaException, ObjectNotFoundException { + protected void checkApprovers(PrismObject object, List expectedApprovers, List realApprovers, OperationResult result) throws SchemaException, ObjectNotFoundException { HashSet realApproversSet = new HashSet(); for (ObjectReferenceType approver : realApprovers) { realApproversSet.add(approver.getOid()); diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/TestCreateOrg.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/TestCreateOrg.java new file mode 100644 index 00000000000..4a9435741b7 --- /dev/null +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/TestCreateOrg.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2010-2015 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.evolveum.midpoint.wf.impl; + +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.model.impl.lens.LensContext; +import com.evolveum.midpoint.prism.delta.ObjectDelta; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +import javax.xml.bind.JAXBException; +import java.io.File; +import java.util.Arrays; + +import static org.testng.AssertJUnit.assertTrue; + +/** + * @author mederly + */ +@ContextConfiguration(locations = {"classpath:ctx-workflow-test-main.xml"}) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public class TestCreateOrg extends AbstractWfTest { + + protected static final Trace LOGGER = TraceManager.getTrace(TestCreateOrg.class); + + private static final File TEST1_FILE = new File(TEST_RESOURCE_DIR, "org-test1.xml"); + private static final String ORG_TEST1_OID = "00000000-1345-3213-4321-432435432034"; + + public TestCreateOrg() throws JAXBException { + super(); + } + + /** + * Create org test1 - rejected + */ + @Test(enabled = true) + public void test010CreateTest1Rejected() throws Exception { + TestUtil.displayTestTile(this, "test010CreateTest1Rejected"); + executeTest("test010CreateTest1Rejected", ORG_TEST1_OID, new TestDetails() { + @Override + int subtaskCount() { + return 1; + } + + @Override + boolean immediate() { + return false; + } + + @Override + boolean checkObjectOnSubtasks() { + return true; + } + + @Override + boolean removeAssignmentsBeforeTest() { + return false; + } + + @Override + public LensContext createModelContext(OperationResult result) throws Exception { + LensContext context = createLensContext(OrgType.class); + addFocusDeltaToContext(context, (ObjectDelta) ObjectDelta.createAddDelta(PrismTestUtil.parseObject(TEST1_FILE))); + return context; + } + + @Override + public void assertsAfterClockworkRun(Task task, OperationResult result) throws Exception { + ModelContext taskModelContext = wfTaskUtil.retrieveModelContext(task, result); + assertTrue("Primary focus delta is not empty", taskModelContext.getFocusContext().getPrimaryDelta().isEmpty()); + assertNoObject(OrgType.class, ORG_TEST1_OID, task, result); + } + + @Override + void assertsRootTaskFinishes(Task task, OperationResult result) throws Exception { + //checkDummyTransportMessages("simpleUserNotifier", 1); + //checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED)); + assertNoObject(OrgType.class, ORG_TEST1_OID, task, result); + } + + @Override + boolean decideOnApproval(String executionId) throws Exception { + return false; + } + }); + } + + /** + * Create org test1 - this time approved + */ + @Test(enabled = true) + public void test020CreateTest1Approved() throws Exception { + TestUtil.displayTestTile(this, "test020CreateTest1Approved"); + executeTest("test020CreateTest1Approved", ORG_TEST1_OID, new TestDetails() { + @Override int subtaskCount() { return 1; } + @Override boolean immediate() { return false; } + @Override boolean checkObjectOnSubtasks() { return true; } + @Override boolean removeAssignmentsBeforeTest() { return false; } + + @Override + public LensContext createModelContext(OperationResult result) throws Exception { + LensContext context = createLensContext(OrgType.class); + addFocusDeltaToContext(context, (ObjectDelta) ObjectDelta.createAddDelta(PrismTestUtil.parseObject(TEST1_FILE))); + return context; + } + + @Override + public void assertsAfterClockworkRun(Task task, OperationResult result) throws Exception { + ModelContext taskModelContext = wfTaskUtil.retrieveModelContext(task, result); + assertTrue("Primary focus delta is not empty", taskModelContext.getFocusContext().getPrimaryDelta().isEmpty()); + assertNoObject(OrgType.class, ORG_TEST1_OID, task, result); + } + + @Override + void assertsRootTaskFinishes(Task task, OperationResult result) throws Exception { + //checkDummyTransportMessages("simpleUserNotifier", 1); + //checkWorkItemAuditRecords(createResultMap(ROLE_R1_OID, WorkflowResult.APPROVED)); + checkApproversForCreate(OrgType.class, ORG_TEST1_OID, Arrays.asList(USER_ADMINISTRATOR_OID), result); + } + + @Override + boolean decideOnApproval(String executionId) throws Exception { + return true; + } + }); + } +} diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/TestUserChangeApproval.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/TestUserChangeApproval.java index 2266482b7d7..cacdfed3506 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/TestUserChangeApproval.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/TestUserChangeApproval.java @@ -31,7 +31,6 @@ import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.path.NameItemPathSegment; 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.xnode.PrimitiveXNode; import com.evolveum.midpoint.schema.result.OperationResult; diff --git a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/general/TestGeneralChangeProcessor.java b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/general/TestGeneralChangeProcessor.java index 45a0c027d08..9a14da6a321 100644 --- a/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/general/TestGeneralChangeProcessor.java +++ b/model/workflow-impl/src/test/java/com/evolveum/midpoint/wf/impl/general/TestGeneralChangeProcessor.java @@ -25,6 +25,7 @@ import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.schema.DeltaConvertor; +import com.evolveum.midpoint.schema.constants.MidPointConstants; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; @@ -134,10 +135,21 @@ public void initSystem(Task initTask, OperationResult initResult) throws Exception { super.initSystem(initTask, initResult); importObjectFromFile(AbstractWfTest.USERS_AND_ROLES_FILENAME, initResult); - + modifyObjectReplaceProperty(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), + new ItemPath(SystemConfigurationType.F_WORKFLOW_CONFIGURATION, + WfConfigurationType.F_PRIMARY_CHANGE_PROCESSOR, + PrimaryChangeProcessorConfigurationType.F_ENABLED), + initTask, initResult, + false); + modifyObjectReplaceProperty(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), + new ItemPath(SystemConfigurationType.F_WORKFLOW_CONFIGURATION, + WfConfigurationType.F_GENERAL_CHANGE_PROCESSOR, + GeneralChangeProcessorConfigurationType.F_ENABLED), + initTask, initResult, + true); } - @Test(enabled = true) + @Test public void test010AddRole1() throws Exception { TestUtil.displayTestTile(this, "test010UserModifyAddRole"); executeTest("test010UserModifyAddRole", USER_JACK_OID, 1, false, true, new ContextCreator() { @@ -192,14 +204,11 @@ void assertsRootTaskFinishes(Task task, OperationResult result) throws Exception }); } - @Test(enabled = true) + @Test public void test020AddAccountRejected() throws Exception { TestUtil.displayTestTile(this, "test020AddAccountRejected"); - primaryChangeProcessor.setEnabled(false); - generalChangeProcessor.setEnabled(true); - generalChangeProcessor.disableScenario("primaryScenario"); - generalChangeProcessor.enableScenario("secondaryScenario"); + enableDisableScenarios(false, true); executeTest("test020AddAccountRejected", USER_JACK_OID, 1, false, true, new ContextCreator() { @Override @@ -252,6 +261,21 @@ void assertsRootTaskFinishes(Task task, OperationResult result) throws Exception }); } + protected void enableDisableScenarios(boolean... values) throws ObjectNotFoundException, SchemaException, com.evolveum.midpoint.util.exception.ExpressionEvaluationException, com.evolveum.midpoint.util.exception.CommunicationException, com.evolveum.midpoint.util.exception.ConfigurationException, com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException, com.evolveum.midpoint.model.api.PolicyViolationException, com.evolveum.midpoint.util.exception.SecurityViolationException { + OperationResult result = new OperationResult("execution"); + Task task = taskManager.createTaskInstance("execution"); + GeneralChangeProcessorConfigurationType gcpConfig = getSystemConfiguration().getWorkflowConfiguration().getGeneralChangeProcessor(); + for (int i = 0; i < values.length; i++) { + gcpConfig.getScenario().get(i).setEnabled(values[i]); + } + modifyObjectReplaceProperty(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value(), + new ItemPath(SystemConfigurationType.F_WORKFLOW_CONFIGURATION, + WfConfigurationType.F_GENERAL_CHANGE_PROCESSOR, + GeneralChangeProcessorConfigurationType.F_ENABLED), + task, result, + gcpConfig); + } + // @Test(enabled = false) // public void test028CurrentRepo() throws Exception { // TestUtil.displayTestTile(this, "test029NewRepo"); @@ -280,14 +304,11 @@ void assertsRootTaskFinishes(Task task, OperationResult result) throws Exception // LOGGER.info("Parsed:\n{}", o.debugDump()); // } - @Test(enabled = true) + @Test public void test030AddAccountApproved() throws Exception { TestUtil.displayTestTile(this, "test030AddAccountApproved"); - primaryChangeProcessor.setEnabled(false); - generalChangeProcessor.setEnabled(true); - generalChangeProcessor.disableScenario("primaryScenario"); - generalChangeProcessor.enableScenario("secondaryScenario"); + enableDisableScenarios(false, true); executeTest("test030AddAccountApproved", USER_JACK_OID, 1, false, true, new ContextCreator() { @Override diff --git a/model/workflow-impl/src/test/resources/common/system-configuration.xml b/model/workflow-impl/src/test/resources/common/system-configuration.xml index 332c7aa685a..02dee95da92 100644 --- a/model/workflow-impl/src/test/resources/common/system-configuration.xml +++ b/model/workflow-impl/src/test/resources/common/system-configuration.xml @@ -64,4 +64,38 @@ target/mail-notifications.log + + + true + + + + + changePasswordAspect + + + + false + + primaryScenario + + + + MyGreatPrimaryProcess + + + secondaryScenario + + + + ApprovingDummyResourceChangesProcess + approvingDummyResourceChangesScenarioBean + + + diff --git a/model/workflow-impl/src/test/resources/org-test1.xml b/model/workflow-impl/src/test/resources/org-test1.xml new file mode 100644 index 00000000000..caa57eab884 --- /dev/null +++ b/model/workflow-impl/src/test/resources/org-test1.xml @@ -0,0 +1,24 @@ + + + + + test1 + Test 1 + functional + diff --git a/model/workflow-impl/src/test/resources/test-config.xml b/model/workflow-impl/src/test/resources/test-config.xml index 4ec01b9719a..cd93eff0750 100644 --- a/model/workflow-impl/src/test/resources/test-config.xml +++ b/model/workflow-impl/src/test/resources/test-config.xml @@ -34,41 +34,6 @@ sa - - - true - - - primaryScenario - - context.getState() == com.evolveum.midpoint.model.api.context.ModelState.PRIMARY - - MyGreatPrimaryProcess - - - secondaryScenario - - - - - - ApprovingDummyResourceChangesProcess - approvingDummyResourceChangesScenarioBean - - - - - true - addRoleAssignmentAspect - modifyRoleAssignmentAspect - addResourceAssignmentAspect - modifyResourceAssignmentAspect - changePasswordAspect - - diff --git a/model/workflow-impl/testng.xml b/model/workflow-impl/testng.xml index 052328b8528..b5084b0f31f 100644 --- a/model/workflow-impl/testng.xml +++ b/model/workflow-impl/testng.xml @@ -20,6 +20,7 @@ +