Skip to content

Commit

Permalink
LDAP Polystring: last fixes (MID-5210)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Apr 3, 2019
1 parent 31e2490 commit 73f5d80
Show file tree
Hide file tree
Showing 9 changed files with 501 additions and 55 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010-2018 Evolveum
* Copyright (c) 2010-2019 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -58,7 +58,9 @@ public boolean match(PolyString a, PolyString b) {
if (a == null || b == null) {
return false;
}
return MiscUtil.equals(a.getOrig(), b.getOrig()) && MiscUtil.equals(a.getNorm(), b.getNorm());
// Delegate to PolyString.equals(). This does it well. As we want to compare
// all aspects of polystring here: orig, norm, translations, langs
return a.equals(b);
}

/* (non-Javadoc)
Expand Down
Expand Up @@ -85,6 +85,7 @@
import com.evolveum.midpoint.test.util.MidPointAsserts;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.JAXBUtil;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
Expand Down Expand Up @@ -145,6 +146,33 @@
@DirtiesContext
public class TestOpenDj extends AbstractOpenDjTest {

protected static final String USER_JACK_FULL_NAME = "Jack Sparrow";

private static final String[] JACK_FULL_NAME_LANG_EN_SK = {
"en", "Jack Sparrow",
"sk", "Džek Sperou"
};

private static final String[] JACK_FULL_NAME_LANG_EN_SK_RU_HR = {
"en", "Jack Sparrow",
"sk", "Džek Sperou",
"ru", "Джек Воробей",
"hr", "Ðek Sperou"
};

private static final String[] JACK_FULL_NAME_LANG_CZ_HR = {
"cz", "Džek Sperou",
"hr", "Ðek Sperou"
};

protected static final String USER_JACK_FULL_NAME_CAPTAIN = "Captain Jack Sparrow";

private static final String[] JACK_FULL_NAME_LANG_CAPTAIN_EN_CZ_SK = {
"en", "Captain Jack Sparrow",
"cz", "Kapitán Džek Sperou",
"sk", "Kapitán Džek Sperou"
};

private static Trace LOGGER = TraceManager.getTrace(TestOpenDj.class);

private String groupSailorOid;
Expand All @@ -163,6 +191,8 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti
openDJController.addEntry("dn: ou=specialgroups,dc=example,dc=com\n"+
"objectclass: organizationalUnit\n"+
"ou: specialgroups\n");

DebugUtil.setDetailedDebugDump(true);
}

@BeforeClass
Expand Down Expand Up @@ -2961,7 +2991,8 @@ public void test472ModifyAccountJackDescriptionOrig() throws Exception {

PolyString descriptionBefore = new PolyString("Bar");

PropertyDelta<PolyString> descriptionDelta = prismContext.deltaFactory().property().create(ItemPath.create(ShadowType.F_ATTRIBUTES, ATTRIBUTE_DESCRIPTION_QNAME),
PropertyDelta<PolyString> descriptionDelta = prismContext.deltaFactory().property().create(
ItemPath.create(ShadowType.F_ATTRIBUTES, ATTRIBUTE_DESCRIPTION_QNAME),
null);
descriptionDelta.setRealValuesToReplace(descriptionBefore);

Expand All @@ -2980,9 +3011,7 @@ public void test472ModifyAccountJackDescriptionOrig() throws Exception {

Entry entry = openDJController.searchByUid("rename");
display("LDAP Entry", entry);
String descriptionStringAfter = OpenDJController.getAttributeValue(entry, ATTRIBUTE_DESCRIPTION_NAME);
assertNotNull("No description in LDAP entry", descriptionStringAfter);
assertEquals("Unexpected description in LDAP entry", descriptionBefore.getOrig(), descriptionStringAfter);
assertDescription(entry, descriptionBefore.getOrig() /* no langs */);

PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class,
ACCOUNT_JACK_OID, null, taskManager.createTaskInstance(), result);
Expand All @@ -2991,10 +3020,220 @@ public void test472ModifyAccountJackDescriptionOrig() throws Exception {

PrismContainer<?> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
PrismProperty<PolyString> descAttr = attributesContainer.findProperty(ATTRIBUTE_DESCRIPTION_QNAME);
PolyString descriptionPolyStringAfter = descAttr.getValues().get(0).getValue();
display("description after (shadow)", descriptionPolyStringAfter);
assertPolyString(descAttr.getValues().get(0).getValue(), "description after (shadow from provisioning)")
.assertOrig(descriptionBefore.getOrig())
.assertNoLangs();

assertShadows(25);
}

/**
* Description is a "language tag" attribute (PolyString).
* Modification with languages.
* MID-5210
*/
@Test
public void test474ModifyAccountJackDescriptionLangEnSk() throws Exception {
final String TEST_NAME = "test474ModifyAccountJackDescriptionLangEnSk";
displayTestTitle(TEST_NAME);

Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();

PolyString descriptionBefore = new PolyString(USER_JACK_FULL_NAME);
descriptionBefore.setLang(MiscUtil.paramsToMap(JACK_FULL_NAME_LANG_EN_SK));

PropertyDelta<PolyString> descriptionDelta = prismContext.deltaFactory().property().create(
ItemPath.create(ShadowType.F_ATTRIBUTES, ATTRIBUTE_DESCRIPTION_QNAME),
null);
descriptionDelta.setRealValuesToReplace(descriptionBefore);

Collection<? extends ItemDelta> modifications = MiscSchemaUtil.createCollection(descriptionDelta);

display("Modifications",modifications);

// WHEN
displayWhen(TEST_NAME);
provisioningService.modifyObject(ShadowType.class, ACCOUNT_JACK_OID,
modifications, null, null, task, result);

// THEN
displayThen(TEST_NAME);
assertSuccess(result);

Entry entry = openDJController.searchByUid("rename");
display("LDAP Entry", entry);
assertDescription(entry, USER_JACK_FULL_NAME, JACK_FULL_NAME_LANG_EN_SK);

PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class,
ACCOUNT_JACK_OID, null, taskManager.createTaskInstance(), result);

display("Object after change",shadow);

PrismContainer<?> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
PrismProperty<PolyString> descAttr = attributesContainer.findProperty(ATTRIBUTE_DESCRIPTION_QNAME);
assertPolyString(descAttr.getValues().get(0).getValue(), "description after (shadow from provisioning)")
.assertOrig(descriptionBefore.getOrig())
.assertLangs(JACK_FULL_NAME_LANG_EN_SK);


assertShadows(25);
}

/**
* Description is a "language tag" attribute (PolyString).
* Modification with more languages.
* MID-5210
*/
@Test
public void test476ModifyAccountJackDescriptionLangEnSkRuHr() throws Exception {
final String TEST_NAME = "test476ModifyAccountJackDescriptionLangEnSkRuHr";
displayTestTitle(TEST_NAME);

Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();

PolyString descriptionBefore = new PolyString(USER_JACK_FULL_NAME);
descriptionBefore.setLang(MiscUtil.paramsToMap(JACK_FULL_NAME_LANG_EN_SK_RU_HR));

PropertyDelta<PolyString> descriptionDelta = prismContext.deltaFactory().property().create(
ItemPath.create(ShadowType.F_ATTRIBUTES, ATTRIBUTE_DESCRIPTION_QNAME),
null);
descriptionDelta.setRealValuesToReplace(descriptionBefore);

Collection<? extends ItemDelta> modifications = MiscSchemaUtil.createCollection(descriptionDelta);

display("Modifications",modifications);

// WHEN
displayWhen(TEST_NAME);
provisioningService.modifyObject(ShadowType.class, ACCOUNT_JACK_OID,
modifications, null, null, task, result);

// THEN
displayThen(TEST_NAME);
assertSuccess(result);

Entry entry = openDJController.searchByUid("rename");
display("LDAP Entry", entry);
assertDescription(entry, USER_JACK_FULL_NAME, JACK_FULL_NAME_LANG_EN_SK_RU_HR);

PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class,
ACCOUNT_JACK_OID, null, taskManager.createTaskInstance(), result);

display("Object after change",shadow);

PrismContainer<?> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
PrismProperty<PolyString> descAttr = attributesContainer.findProperty(ATTRIBUTE_DESCRIPTION_QNAME);
assertPolyString(descAttr.getValues().get(0).getValue(), "description after (shadow from provisioning)")
.assertOrig(descriptionBefore.getOrig())
.assertLangs(JACK_FULL_NAME_LANG_EN_SK_RU_HR);


assertShadows(25);
}

/**
* Description is a "language tag" attribute (PolyString).
* Modification with languages, some are new, some are deleted.
* MID-5210
*/
@Test
public void test478ModifyAccountJackDescriptionLangEnSkRuHr() throws Exception {
final String TEST_NAME = "test478ModifyAccountJackDescriptionLangEnSkRuHr";
displayTestTitle(TEST_NAME);

Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();

PolyString descriptionBefore = new PolyString(USER_JACK_FULL_NAME);
descriptionBefore.setLang(MiscUtil.paramsToMap(JACK_FULL_NAME_LANG_CZ_HR));

PropertyDelta<PolyString> descriptionDelta = prismContext.deltaFactory().property().create(
ItemPath.create(ShadowType.F_ATTRIBUTES, ATTRIBUTE_DESCRIPTION_QNAME),
null);
descriptionDelta.setRealValuesToReplace(descriptionBefore);

Collection<? extends ItemDelta> modifications = MiscSchemaUtil.createCollection(descriptionDelta);

display("Modifications",modifications);

// WHEN
displayWhen(TEST_NAME);
provisioningService.modifyObject(ShadowType.class, ACCOUNT_JACK_OID,
modifications, null, null, task, result);

// THEN
displayThen(TEST_NAME);
assertSuccess(result);

Entry entry = openDJController.searchByUid("rename");
display("LDAP Entry", entry);
assertDescription(entry, USER_JACK_FULL_NAME, JACK_FULL_NAME_LANG_CZ_HR);

PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class,
ACCOUNT_JACK_OID, null, taskManager.createTaskInstance(), result);

display("Object after change",shadow);

PrismContainer<?> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
PrismProperty<PolyString> descAttr = attributesContainer.findProperty(ATTRIBUTE_DESCRIPTION_QNAME);
assertPolyString(descAttr.getValues().get(0).getValue(), "description after (shadow from provisioning)")
.assertOrig(descriptionBefore.getOrig())
.assertLangs(JACK_FULL_NAME_LANG_CZ_HR);


assertShadows(25);
}

/**
* Description is a "language tag" attribute (PolyString).
* Modification without any values. Clean slate again.
* MID-5210
*/
@Test
public void test479ModifyAccountJackDescriptionJack() throws Exception {
final String TEST_NAME = "test479ModifyAccountJackDescriptionJack";
displayTestTitle(TEST_NAME);

Task task = createTask(TEST_NAME);
OperationResult result = task.getResult();

PolyString descriptionBefore = new PolyString(USER_JACK_FULL_NAME);

PropertyDelta<PolyString> descriptionDelta = prismContext.deltaFactory().property().create(
ItemPath.create(ShadowType.F_ATTRIBUTES, ATTRIBUTE_DESCRIPTION_QNAME),
null);
descriptionDelta.setRealValuesToReplace(descriptionBefore);

Collection<? extends ItemDelta> modifications = MiscSchemaUtil.createCollection(descriptionDelta);

display("Modifications",modifications);

// WHEN
displayWhen(TEST_NAME);
provisioningService.modifyObject(ShadowType.class, ACCOUNT_JACK_OID,
modifications, null, null, task, result);

// THEN
displayThen(TEST_NAME);
assertSuccess(result);

Entry entry = openDJController.searchByUid("rename");
display("LDAP Entry", entry);
assertDescription(entry, USER_JACK_FULL_NAME /* no langs */);

PrismObject<ShadowType> shadow = provisioningService.getObject(ShadowType.class,
ACCOUNT_JACK_OID, null, taskManager.createTaskInstance(), result);

display("Object after change",shadow);

PrismContainer<?> attributesContainer = shadow.findContainer(ShadowType.F_ATTRIBUTES);
PrismProperty<PolyString> descAttr = attributesContainer.findProperty(ATTRIBUTE_DESCRIPTION_QNAME);
assertPolyString(descAttr.getValues().get(0).getValue(), "description after (shadow from provisioning)")
.assertOrig(descriptionBefore.getOrig())
.assertNoLangs();

assertEquals("Wrong orig in description polystring (shadow)", descriptionBefore.getOrig(), descriptionPolyStringAfter.getOrig());

assertShadows(25);
}
Expand Down Expand Up @@ -3174,4 +3413,8 @@ protected void assertEntitlementGroup(PrismObject<ShadowType> account, String en
protected void assertConnectorOperationIncrement(int expectedIncrementSmart, int expectedIncrementDumb) {
assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, expectedIncrementSmart);
}

private void assertDescription(Entry entry, String expectedOrigValue, String... params) {
OpenDJController.assertAttributeLang(entry, ATTRIBUTE_DESCRIPTION_NAME, expectedOrigValue, params);
}
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2010-2017 Evolveum
~ Copyright (c) 2010-2019 Evolveum
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -101,6 +101,13 @@
<matchingRule>mr:xml</matchingRule> <!-- matching rule override. Secretary is normally distinguishedName -->
<fetchStrategy>explicit</fetchStrategy>
</attribute>
<attribute>
<ref>ri:description</ref>
<limitations>
<!-- Poly-attributes only work with single-value attributes -->
<maxOccurs>1</maxOccurs>
</limitations>
</attribute>
<association>
<ref>ri:group</ref>
<displayName>LDAP Group Membership</displayName>
Expand Down
Expand Up @@ -430,6 +430,9 @@ private Object polyStringFromConnIdMap(Map<String,String> connIdMap) {
lang.put(key, connIdMapEntry.getValue());
}
}
if (orig == null) {
return null;
}
PolyString polyString = new PolyString(orig);
polyString.setLang(lang);
return polyString;
Expand Down
Expand Up @@ -69,6 +69,7 @@
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.test.asserter.AbstractAsserter;
import com.evolveum.midpoint.test.asserter.ShadowAsserter;
import com.evolveum.midpoint.test.asserter.prism.PolyStringAsserter;
import com.evolveum.midpoint.test.asserter.refinedschema.RefinedResourceSchemaAsserter;
import com.evolveum.midpoint.test.ldap.OpenDJController;
import com.evolveum.midpoint.test.util.DerbyController;
Expand Down Expand Up @@ -2423,6 +2424,12 @@ protected void initializeAsserter(AbstractAsserter<?> asserter) {
asserter.setProtector(protector);
}

protected PolyStringAsserter<Void> assertPolyString(PolyString polystring, String desc) {
PolyStringAsserter<Void> asserter = new PolyStringAsserter<>(polystring, desc);
initializeAsserter(asserter);
return asserter;
}

protected RefinedResourceSchemaAsserter<Void> assertRefinedResourceSchema(PrismObject<ResourceType> resource, String details) throws SchemaException {
RefinedResourceSchema refinedSchema = RefinedResourceSchemaImpl.getRefinedSchema(resource, prismContext);
assertNotNull("No refined schema for "+resource+" ("+details+")", refinedSchema);
Expand Down
Expand Up @@ -101,6 +101,11 @@ public PolyStringAsserter<RA> assertLangs(String... expectedParams) {
return this;
}

public PolyStringAsserter<RA> assertNoLangs() {
assertNull("Unexpected langs in "+desc(), polystring.getLang());
return this;
}

protected String desc() {
return descWithDetails(polystring);
}
Expand Down

0 comments on commit 73f5d80

Please sign in to comment.