Skip to content

Commit

Permalink
Tag expression (MID-3542)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Apr 29, 2019
1 parent feff2b9 commit 6069771
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 92 deletions.
Expand Up @@ -38,7 +38,7 @@
import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.model.impl.lens.SynchronizationIntent;
import com.evolveum.midpoint.model.impl.messaging.MessageWrapper;
import com.evolveum.midpoint.model.impl.sync.CorrelationConfirmationEvaluator;
import com.evolveum.midpoint.model.impl.sync.SynchronizationExpressionsEvaluator;
import com.evolveum.midpoint.model.impl.sync.SynchronizationContext;
import com.evolveum.midpoint.model.impl.sync.SynchronizationServiceUtils;
import com.evolveum.midpoint.prism.*;
Expand Down Expand Up @@ -130,7 +130,7 @@ public class MidpointFunctionsImpl implements MidpointFunctions {
@Autowired private ConstantsManager constantsManager;
@Autowired private LocalizationService localizationService;
@Autowired private ExpressionFactory expressionFactory;
@Autowired private CorrelationConfirmationEvaluator correlationConfirmationEvaluator;
@Autowired private SynchronizationExpressionsEvaluator correlationConfirmationEvaluator;
@Autowired private ArchetypeManager archetypeManager;

@Autowired
Expand Down
Expand Up @@ -39,7 +39,7 @@
import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.model.impl.lens.LensUtil;
import com.evolveum.midpoint.model.impl.lens.projector.focus.AssignmentProcessor;
import com.evolveum.midpoint.model.impl.sync.CorrelationConfirmationEvaluator;
import com.evolveum.midpoint.model.impl.sync.SynchronizationExpressionsEvaluator;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.PropertyDelta;
Expand Down Expand Up @@ -106,7 +106,7 @@ public class ProjectionValuesProcessor {
private PrismContext prismContext;

@Autowired
private CorrelationConfirmationEvaluator correlationConfirmationEvaluator;
private SynchronizationExpressionsEvaluator correlationConfirmationEvaluator;

@Autowired
private SynchronizationService synchronizationService;
Expand Down
Expand Up @@ -60,17 +60,19 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConditionalSearchFilterType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExpressionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectMultiplicityType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowTagSpecificationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;

import java.util.HashSet;
import java.util.Set;

@Component
public class CorrelationConfirmationEvaluator {
public class SynchronizationExpressionsEvaluator {

private static transient Trace LOGGER = TraceManager.getTrace(CorrelationConfirmationEvaluator.class);
private static transient Trace LOGGER = TraceManager.getTrace(SynchronizationExpressionsEvaluator.class);

@Autowired @Qualifier("cacheRepositoryService") private RepositoryService repositoryService;
@Autowired private PrismContext prismContext;
Expand Down Expand Up @@ -147,7 +149,7 @@ private boolean satisfyCondition(ShadowType currentShadow, ConditionalSearchFilt
ExpressionType condition = conditionalFilter.getCondition();
ExpressionVariables variables = ModelImplUtils.getDefaultExpressionVariables(null,currentShadow, resourceType, configurationType, prismContext);
ItemDefinition outputDefinition = prismContext.definitionFactory().createPropertyDefinition(
ExpressionConstants.OUTPUT_ELEMENT_NAME, DOMUtil.XSD_BOOLEAN);
ExpressionConstants.OUTPUT_ELEMENT_NAME, PrimitiveType.BOOLEAN.getQname());
PrismPropertyValue<Boolean> satisfy = (PrismPropertyValue) ExpressionUtil.evaluateExpression(variables,
outputDefinition, condition, expressionProfile, expressionFactory, shortDesc, task, parentResult);
if (satisfy.getValue() == null) {
Expand Down Expand Up @@ -398,4 +400,29 @@ public <F extends FocusType> boolean evaluateConfirmationExpression(Class<F> foc
return resultVal;
}

// For now only used in sync service. but later can be used in outbound/assignments
public String generateTag(ResourceObjectMultiplicityType multiplicity, PrismObject<ShadowType> shadow, PrismObject<ResourceType> resource, PrismObject<SystemConfigurationType> configuration, String shortDesc, Task task, OperationResult parentResult) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException {
if (multiplicity == null) {
return null;
}
ShadowTagSpecificationType tagSpec = multiplicity.getTag();
if (tagSpec == null) {
return shadow.getOid();
}
ExpressionType expressionType = tagSpec.getExpression();
if (expressionType == null) {
return shadow.getOid();
}

ExpressionVariables variables = ModelImplUtils.getDefaultExpressionVariables(null, shadow, null, resource, configuration, null, prismContext);
ItemDefinition outputDefinition = prismContext.definitionFactory().createPropertyDefinition(
ExpressionConstants.OUTPUT_ELEMENT_NAME, PrimitiveType.STRING.getQname());
PrismPropertyValue<String> tagProp = (PrismPropertyValue) ExpressionUtil.evaluateExpression(variables,
outputDefinition, expressionType, MiscSchemaUtil.getExpressionProfile(), expressionFactory, shortDesc, task, parentResult);
if (tagProp == null) {
return null;
}
return tagProp.getRealValue();
}

}
Expand Up @@ -102,7 +102,7 @@ public class SynchronizationServiceImpl implements SynchronizationService {
private static final Trace LOGGER = TraceManager.getTrace(SynchronizationServiceImpl.class);

@Autowired private ActionManager<Action> actionManager;
@Autowired private CorrelationConfirmationEvaluator correlationConfirmationEvaluator;
@Autowired private SynchronizationExpressionsEvaluator synchronizationExpressionsEvaluator;
@Autowired private ContextFactory contextFactory;
@Autowired private Clockwork clockwork;
@Autowired private ExpressionFactory expressionFactory;
Expand Down Expand Up @@ -241,7 +241,7 @@ public <F extends FocusType> SynchronizationContext<F> loadSynchronizationContex
return syncCtx;
}

private <F extends FocusType> void processTag(SynchronizationContext<F> syncCtx) throws SchemaException {
private <F extends FocusType> void processTag(SynchronizationContext<F> syncCtx) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException, CommunicationException, ConfigurationException, SecurityViolationException {
PrismObject<ShadowType> applicableShadow = syncCtx.getApplicableShadow();
if (applicableShadow == null) {
return;
Expand All @@ -262,8 +262,8 @@ private <F extends FocusType> void processTag(SynchronizationContext<F> syncCtx)
if (maxOccurs == null || maxOccurs.equals("1")) {
return;
}
// TODO: generate tag: expression
String tag = applicableShadow.getOid();
String tag = synchronizationExpressionsEvaluator.generateTag(multiplicity, applicableShadow,
syncCtx.getResource(), syncCtx.getSystemConfiguration(), "tag expression for "+applicableShadow, syncCtx.getTask(), syncCtx.getResult());
LOGGER.debug("SYNCHRONIZATION: TAG generated: {}", tag);
syncCtx.setTag(tag);
}
Expand Down Expand Up @@ -622,7 +622,7 @@ public <F extends FocusType> boolean matchUserCorrelationRule(PrismObject<Shadow
ExpressionEvaluationException, CommunicationException, SecurityViolationException {

SynchronizationContext<F> synchronizationContext = loadSynchronizationContext(shadow, shadow, resourceType.asPrismObject(), task.getChannel(), configuration, task, result);
return correlationConfirmationEvaluator.matchFocusByCorrelationRule(synchronizationContext, focus);
return synchronizationExpressionsEvaluator.matchFocusByCorrelationRule(synchronizationContext, focus);
}

/**
Expand Down Expand Up @@ -673,7 +673,7 @@ private <F extends FocusType> void determineSituationWithCorrelation(Synchroniza
SynchronizationSituationType state;
LOGGER.trace("SYNCHRONIZATION: CORRELATION: Looking for list of {} objects based on correlation rule.",
syncCtx.getFocusClass().getSimpleName());
List<PrismObject<F>> users = correlationConfirmationEvaluator.findFocusesByCorrelationRule(syncCtx.getFocusClass(),
List<PrismObject<F>> users = synchronizationExpressionsEvaluator.findFocusesByCorrelationRule(syncCtx.getFocusClass(),
resourceShadow.asObjectable(), syncCtx.getCorrelation(), resource,
syncCtx.getSystemConfiguration().asObjectable(), task, result);
if (users == null) {
Expand All @@ -685,7 +685,7 @@ private <F extends FocusType> void determineSituationWithCorrelation(Synchroniza
LOGGER.trace("SYNCHRONIZATION: CONFIRMATION: no confirmation defined.");
} else {
LOGGER.debug("SYNCHRONIZATION: CONFIRMATION: Checking objects from correlation with confirmation rule.");
users = correlationConfirmationEvaluator.findUserByConfirmationRule(syncCtx.getFocusClass(), users,
users = synchronizationExpressionsEvaluator.findUserByConfirmationRule(syncCtx.getFocusClass(), users,
resourceShadow.asObjectable(), resource, syncCtx.getSystemConfiguration().asObjectable(),
syncCtx.getConfirmation(), task, result);
}
Expand Down
Expand Up @@ -69,7 +69,7 @@ public class TestCorrelationConfiramtionEvaluator extends AbstractInternalModelI
private RepositoryService repositoryService;

@Autowired(required = true)
private CorrelationConfirmationEvaluator evaluator;
private SynchronizationExpressionsEvaluator evaluator;

@Test
public void test001CorrelationOrFilter() throws Exception{
Expand Down
Expand Up @@ -64,12 +64,23 @@ public class TestMultiAccount extends AbstractInitializedModelIntegrationTest {

protected static final String ACCOUNT_MUAD_DIB_USERNAME = "muaddib";
protected static final String ACCOUNT_MUAD_DIB_FULL_NAME = "Muad'Dib";

protected static final String ACCOUNT_DUKE_USERNAME = "duke";
protected static final String ACCOUNT_DUKE_FULL_NAME = "Duke Paul Atreides";
protected static final String ACCOUNT_DUKE_TITLE = "duke";

protected static final String ACCOUNT_MAHDI_USERNAME = "mahdi";
protected static final String ACCOUNT_MAHDI_FULL_NAME = "Mahdi Muad'Dib";
protected static final String ACCOUNT_MAHDI_TITLE = "mahdi";

private static final String INTENT_ADMIN = "admin";

protected static final String TITLE_DUKE = "Duke";

private String accountPaulOid;

private String accountMuaddibOid;
private String accountDukeOid;

private String accountMahdiOid;

@Override
public void initSystem(Task initTask, OperationResult initResult) throws Exception {
Expand Down Expand Up @@ -183,7 +194,8 @@ public void test100ImportMuadDib() throws Exception {
.displayWithProjections()
.assertFullName(ACCOUNT_PAUL_ATREIDES_FULL_NAME)
.assertEmployeeNumber(ACCOUNT_PAUL_ATREIDES_ID)
.assertOrganizationalUnits(ACCOUNT_PAUL_ATREIDES_FULL_NAME, ACCOUNT_MUAD_DIB_FULL_NAME)
// TODO
// .assertOrganizationalUnits(ACCOUNT_PAUL_ATREIDES_FULL_NAME, ACCOUNT_MUAD_DIB_FULL_NAME)
.links()
.assertLinks(2)
.link(accountPaulOid)
Expand All @@ -205,6 +217,152 @@ public void test100ImportMuadDib() throws Exception {
.getOid();


assertUsers(getNumberOfUsers() + 1);

}

/**
* Import another account that correlates to Paul. This has the same resource+kind+intent.
* But this is an admin account (title=duke). Therefore it will have different intent.
* And there is a custom tag expression.
*/
@Test
public void test200ImportDuke() throws Exception {
final String TEST_NAME = "test200ImportDuke";
displayTestTitle(TEST_NAME);

// GIVEN
Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

DummyAccount account = new DummyAccount(ACCOUNT_DUKE_USERNAME);
account.setEnabled(true);
account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, ACCOUNT_DUKE_FULL_NAME);
account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_SHIP_NAME, ACCOUNT_PAUL_ATREIDES_ID);
account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, ACCOUNT_DUKE_TITLE);
getDummyResource(RESOURCE_DUMMY_MULTI_GREEN_NAME).addAccount(account);

// Preconditions
assertUsers(getNumberOfUsers() + 1);

// WHEN
displayWhen(TEST_NAME);
importMultiGreenAccounts(task, result);

// THEN
displayThen(TEST_NAME);

accountDukeOid = assertUserAfterByUsername(ACCOUNT_PAUL_ATREIDES_USERNAME)
.displayWithProjections()
.assertFullName(ACCOUNT_PAUL_ATREIDES_FULL_NAME)
.assertEmployeeNumber(ACCOUNT_PAUL_ATREIDES_ID)
// TODO
// .assertOrganizationalUnits(ACCOUNT_PAUL_ATREIDES_FULL_NAME, ACCOUNT_MUAD_DIB_FULL_NAME)
.links()
.assertLinks(3)
.link(accountPaulOid)
.resolveTarget()
.display()
.assertKind(ShadowKindType.ACCOUNT)
.assertIntent(SchemaConstants.INTENT_DEFAULT)
.assertTag(accountPaulOid)
.end()
.end()
.link(accountMuaddibOid)
.resolveTarget()
.display()
.assertKind(ShadowKindType.ACCOUNT)
.assertIntent(SchemaConstants.INTENT_DEFAULT)
.assertTag(accountMuaddibOid)
.end()
.end()
.by()
.notTags(accountPaulOid, accountMuaddibOid)
.find()
.resolveTarget()
.display()
.assertKind(ShadowKindType.ACCOUNT)
.assertIntent(INTENT_ADMIN)
.assertTag(ACCOUNT_DUKE_TITLE)
.getOid();


assertUsers(getNumberOfUsers() + 1);

}

/**
* Import yet another admin account that correlates to Paul.
*/
@Test
public void test210ImportMahdi() throws Exception {
final String TEST_NAME = "test210ImportMahdi";
displayTestTitle(TEST_NAME);

// GIVEN
Task task = createTask(AbstractSynchronizationStoryTest.class.getName() + "." + TEST_NAME);
OperationResult result = task.getResult();

DummyAccount account = new DummyAccount(ACCOUNT_MAHDI_USERNAME);
account.setEnabled(true);
account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_FULLNAME_NAME, ACCOUNT_MAHDI_FULL_NAME);
account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_SHIP_NAME, ACCOUNT_PAUL_ATREIDES_ID);
account.addAttributeValues(DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_TITLE_NAME, ACCOUNT_MAHDI_TITLE);
getDummyResource(RESOURCE_DUMMY_MULTI_GREEN_NAME).addAccount(account);

// Preconditions
assertUsers(getNumberOfUsers() + 1);

// WHEN
displayWhen(TEST_NAME);
importMultiGreenAccounts(task, result);

// THEN
displayThen(TEST_NAME);

accountMahdiOid = assertUserAfterByUsername(ACCOUNT_PAUL_ATREIDES_USERNAME)
.displayWithProjections()
.assertFullName(ACCOUNT_PAUL_ATREIDES_FULL_NAME)
.assertEmployeeNumber(ACCOUNT_PAUL_ATREIDES_ID)
// TODO
// .assertOrganizationalUnits(ACCOUNT_PAUL_ATREIDES_FULL_NAME, ACCOUNT_MUAD_DIB_FULL_NAME)
.links()
.assertLinks(4)
.link(accountPaulOid)
.resolveTarget()
.display()
.assertKind(ShadowKindType.ACCOUNT)
.assertIntent(SchemaConstants.INTENT_DEFAULT)
.assertTag(accountPaulOid)
.end()
.end()
.link(accountMuaddibOid)
.resolveTarget()
.display()
.assertKind(ShadowKindType.ACCOUNT)
.assertIntent(SchemaConstants.INTENT_DEFAULT)
.assertTag(accountMuaddibOid)
.end()
.end()
.link(accountDukeOid)
.resolveTarget()
.display()
.assertKind(ShadowKindType.ACCOUNT)
.assertIntent(INTENT_ADMIN)
.assertTag(ACCOUNT_DUKE_TITLE)
.end()
.end()
.by()
.notTags(accountPaulOid, accountMuaddibOid, ACCOUNT_DUKE_TITLE)
.find()
.resolveTarget()
.display()
.assertKind(ShadowKindType.ACCOUNT)
.assertIntent(INTENT_ADMIN)
.assertTag(ACCOUNT_MAHDI_TITLE)
.getOid();


assertUsers(getNumberOfUsers() + 1);

}
Expand Down

0 comments on commit 6069771

Please sign in to comment.