From 80501d9cf2b45144420f9d95b332595466c21356 Mon Sep 17 00:00:00 2001
From: "Katarina Valalikova (katkav)"
Date: Mon, 29 Sep 2014 10:02:15 +0200
Subject: [PATCH 01/19] loading full shadow for dependency computation (if
specified)
---
.../schema/util/ResourceTypeUtil.java | 9 +++++++++
.../xml/ns/public/common/common-3.xsd | 8 ++++++++
.../lens/projector/DependencyProcessor.java | 19 ++++++++++++++++---
.../model/impl/lens/projector/Projector.java | 4 ++--
4 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java
index 90c66dd5c4a..5067a6ea812 100644
--- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java
+++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ResourceTypeUtil.java
@@ -447,6 +447,15 @@ public static ResourceObjectTypeDependencyStrictnessType getDependencyStrictness
}
}
+ public static boolean isForceLoadDependentShadow(ResourceObjectTypeDependencyType dependency){
+ Boolean force = dependency.isForceLoad();
+ if (force == null){
+ return false;
+ }
+
+ return force;
+ }
+
public static boolean isDown(ResourceType resource){
return (resource.getOperationalState() != null && AvailabilityStatusType.DOWN == resource.getOperationalState().getLastAvailabilityStatus());
}
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 ac1f922f9cd..efc41fac072 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
@@ -3425,6 +3425,14 @@
+
+
+
+ Specifies if the shadow on which we depends has to be load. By default we do
+ not force to load full dependent shadow.
+
+
+
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
index 01be826b487..1c0fe8abc9c 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
@@ -38,6 +38,7 @@
import com.evolveum.midpoint.model.impl.lens.LensUtil;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
+import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ResourceTypeUtil;
import com.evolveum.midpoint.task.api.Task;
@@ -65,6 +66,9 @@ public class DependencyProcessor {
private static final Trace LOGGER = TraceManager.getTrace(DependencyProcessor.class);
+ @Autowired
+ private ProvisioningService provisioningService;
+
public void resetWaves(LensContext context) throws PolicyViolationException {
}
@@ -333,7 +337,7 @@ private LensProjectionContext createAnotherContext(LensCo
* and stuff like that.
*/
public boolean checkDependencies(LensContext context,
- LensProjectionContext projContext) throws PolicyViolationException {
+ LensProjectionContext projContext, OperationResult result) throws PolicyViolationException {
if (projContext.isDelete()) {
// It is OK if we depend on something that is not there if we are being removed ... for now
return true;
@@ -402,6 +406,15 @@ public boolean checkDependencies(LensContext context,
|| strictness == ResourceObjectTypeDependencyStrictnessType.RELAXED) {
if (wasProvisioned(dependencyAccountContext, context.getExecutionWave())) {
// everything OK
+ if (ResourceTypeUtil.isForceLoadDependentShadow(dependency) && !dependencyAccountContext.isFullShadow()){
+ try {
+ LensUtil.loadFullAccount(context, dependencyAccountContext, provisioningService, result);
+ } catch (ObjectNotFoundException | CommunicationException | SchemaException
+ | ConfigurationException | SecurityViolationException e) {
+ // this is not fatal error. we can continue without full account..the incosinstencies will be treaten later, by reconciliation
+ LOGGER.warn("Could not load dependent shadow, continue with the shadow loaded before.");
+ }
+ }
} else {
// We do not want to throw exception here. That will stop entire projection.
// Let's just mark the projection as broken and skip it.
@@ -425,10 +438,10 @@ public boolean checkDependencies(LensContext context,
* Finally checks for all the dependencies. Some dependencies cannot be checked during wave computations as
* we might not have all activation decisions yet.
*/
- public void checkDependenciesFinal(LensContext context) throws PolicyViolationException {
+ public void checkDependenciesFinal(LensContext context, OperationResult result) throws PolicyViolationException {
for (LensProjectionContext accountContext: context.getProjectionContexts()) {
- checkDependencies(context, accountContext);
+ checkDependencies(context, accountContext, result);
}
for (LensProjectionContext accountContext: context.getProjectionContexts()) {
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java
index dc23bdde740..65b2cad2fa6 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java
@@ -211,7 +211,7 @@ public void project(LensContext context, String activi
if (consistencyChecks) context.checkConsistence();
- if (!dependencyProcessor.checkDependencies(context, projectionContext)) {
+ if (!dependencyProcessor.checkDependencies(context, projectionContext, result)) {
continue;
}
@@ -255,7 +255,7 @@ public void project(LensContext context, String activi
// We can do this only when computation of all the waves is finished. Before that we do not know
// activation of every account and therefore cannot decide what is OK and what is not
- dependencyProcessor.checkDependenciesFinal(context);
+ dependencyProcessor.checkDependenciesFinal(context, result);
if (consistencyChecks) context.checkConsistence();
From d4896e7330502b299da5322b22f998074fc5dd67 Mon Sep 17 00:00:00 2001
From: "Katarina Valalikova (katkav)"
Date: Thu, 2 Oct 2014 09:27:02 +0200
Subject: [PATCH 02/19] fixing inbound - outbound processing for dependency..
---
.../dummy/connector/DummyConfiguration.java | 14 +++
.../icf/dummy/connector/DummyConnector.java | 5 +-
.../icf/dummy/resource/DummyAccount.java | 1 +
.../icf/dummy/resource/DummyObject.java | 3 +-
.../icf/dummy/resource/DummyResource.java | 27 +++++-
.../midpoint/model/impl/lens/LensUtil.java | 2 +-
.../lens/projector/AssignmentProcessor.java | 15 ++++
.../lens/projector/DependencyProcessor.java | 85 ++++++++++++++++---
.../model/impl/lens/projector/Projector.java | 5 +-
.../test/AbstractModelIntegrationTest.java | 9 ++
.../midpoint/test/DummyResourceContoller.java | 2 +-
.../midpoint/testing/story/TestTrafo.java | 16 +++-
.../story/src/test/resources/schema/trafo.xsd | 7 ++
.../resources/trafo/resource-dummy-ad.xml | 10 +++
.../resources/trafo/resource-dummy-mail.xml | 11 +++
15 files changed, 190 insertions(+), 22 deletions(-)
diff --git a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java
index 0e511873e44..d5740c1cf09 100644
--- a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java
+++ b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConfiguration.java
@@ -44,6 +44,7 @@ public class DummyConfiguration extends AbstractConfiguration {
private boolean requireExplicitEnable = false;
private boolean caseIgnoreId = false;
private boolean caseIgnoreValues = false;
+ private boolean generateDefaultValues = false;
private boolean tolerateDuplicateValues = true;
private String uselessString;
private GuardedString uselessGuardedString;
@@ -160,6 +161,19 @@ public boolean getCaseIgnoreId() {
public void setCaseIgnoreId(boolean caseIgnoreId) {
this.caseIgnoreId = caseIgnoreId;
}
+
+ /**
+ * If set to true then the "home dir" will be generated
+ */
+ @ConfigurationProperty(displayMessageKey = "UI_GENERATE_DEFAULT_VALUES",
+ helpMessageKey = "UI_GENERATE_DEFAULT_VALUES")
+ public boolean isGenerateDefaultValues() {
+ return generateDefaultValues;
+ }
+
+ public void setGenerateDefaultValues(boolean generateDefaultValues) {
+ this.generateDefaultValues = generateDefaultValues;
+ }
/**
* If set to true then the attribute values will be considered case-insensitive
diff --git a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java
index 296ef2419fa..26963cfc080 100644
--- a/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java
+++ b/icf-connectors/dummy-connector/src/main/java/com/evolveum/icf/dummy/connector/DummyConnector.java
@@ -144,6 +144,7 @@ public void init(Configuration configuration) {
resource.setCaseIgnoreValues(this.configuration.getCaseIgnoreValues());
resource.setEnforceUniqueName(this.configuration.isEnforceUniqueName());
resource.setTolerateDuplicateValues(this.configuration.getTolerateDuplicateValues());
+ resource.setGenerateDefaultValues(this.configuration.isGenerateDefaultValues());
resource.setUselessString(this.configuration.getUselessString());
GuardedString uselessGuardedString = this.configuration.getUselessGuardedString();
@@ -227,6 +228,8 @@ public Uid create(final ObjectClass objectClass, final Set createAttr
throw new ConnectionFailedException(e.getMessage(), e);
} catch (FileNotFoundException e) {
throw new ConnectorIOException(e.getMessage(), e);
+ } catch (SchemaViolationException e) {
+ throw new ConnectorException(e);
}
String id;
@@ -1065,7 +1068,7 @@ private ConnectorObjectBuilder createConnectorObjectBuilderCommon(DummyObject du
(attributesToGet == null || attributesToGet.contains(OperationalAttributes.DISABLE_DATE_NAME))) {
builder.addAttribute(OperationalAttributes.DISABLE_DATE_NAME, convertToLong(dummyObject.getValidTo()));
}
- }
+ }
return builder;
}
diff --git a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAccount.java b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAccount.java
index a6bffeb440c..a3f201ee035 100644
--- a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAccount.java
+++ b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyAccount.java
@@ -38,6 +38,7 @@ public class DummyAccount extends DummyObject {
public static final String ATTR_DESCRIPTION_NAME = "description";
public static final String ATTR_INTERESTS_NAME = "interests";
public static final String ATTR_PRIVILEGES_NAME = "privileges";
+ public static final String ATTR_INTERNAL_ID = "internalId";
private String password = null;
private Boolean lockout = null;
diff --git a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java
index 49facb282d2..87dbb7f80aa 100644
--- a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java
+++ b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyObject.java
@@ -41,6 +41,7 @@
public abstract class DummyObject implements DebugDumpable {
private String id;
+// private int internalId = -1;
private String name;
private Map> attributes = new HashMap>();
private boolean enabled = true;
@@ -60,7 +61,7 @@ public String getId() {
public void setId(String id) {
this.id = id;
}
-
+
public DummyObject(String name) {
this.name = name;
}
diff --git a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyResource.java b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyResource.java
index fb39b6081b0..535021a0b6f 100644
--- a/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyResource.java
+++ b/icf-connectors/dummy-resource/src/main/java/com/evolveum/icf/dummy/resource/DummyResource.java
@@ -77,6 +77,7 @@ public class DummyResource implements DebugDumpable {
private List deltas;
private int latestSyncToken;
private boolean tolerateDuplicateValues = false;
+ private boolean generateDefaultValues = false;
private boolean enforceUniqueName = true;
private boolean enforceSchema = true;
private boolean caseIgnoreId = false;
@@ -88,6 +89,7 @@ public class DummyResource implements DebugDumpable {
private BreakMode modifyBreakMode = BreakMode.NONE;
private BreakMode deleteBreakMode = BreakMode.NONE;
+
// Following two properties are just copied from the connector
// configuration and can be checked later. They are otherwise
// completely useless.
@@ -149,6 +151,14 @@ public void setTolerateDuplicateValues(boolean tolerateDuplicateValues) {
this.tolerateDuplicateValues = tolerateDuplicateValues;
}
+ public boolean isGenerateDefaultValues() {
+ return generateDefaultValues;
+ }
+
+ public void setGenerateDefaultValues(boolean generateDefaultValues) {
+ this.generateDefaultValues = generateDefaultValues;
+ }
+
public boolean isEnforceUniqueName() {
return enforceUniqueName;
}
@@ -418,7 +428,7 @@ public Collection listPrivileges() throws ConnectException, File
}
}
- private synchronized String addObject(Map map, T newObject) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException {
+ private synchronized String addObject(Map map, T newObject) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException, SchemaViolationException {
if (addBreakMode == BreakMode.NONE) {
// just go on
} else if (addBreakMode == BreakMode.NETWORK) {
@@ -446,6 +456,13 @@ private synchronized String addObject(Map map,
throw new IllegalStateException("The hell is frozen over. The impossible has happened. ID "+newId+" already exists ("+ type.getSimpleName()+" with identifier "+normalName+")");
}
+ //this is "resource-generated" attribute (used to simulate resource which generate by default attributes which we need to sync)
+ if (generateDefaultValues){
+ int internalId = allObjects.size();
+ newObject.addAttributeValue(DummyAccount.ATTR_INTERNAL_ID, internalId++);
+ }
+
+
String mapKey;
if (enforceUniqueName) {
mapKey = normalName;
@@ -470,6 +487,7 @@ private synchronized String addObject(Map map,
return newObject.getName();
}
+
private synchronized void deleteObjectByName(Class type, Map map, String name) throws ObjectDoesNotExistException, ConnectException, FileNotFoundException {
if (deleteBreakMode == BreakMode.NONE) {
// go on
@@ -615,7 +633,7 @@ private void renameObject(Class type, Map m
existingObject.setName(newName);
}
- public String addAccount(DummyAccount newAccount) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException {
+ public String addAccount(DummyAccount newAccount) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException, SchemaViolationException {
return addObject(accounts, newAccount);
}
@@ -627,7 +645,7 @@ public void renameAccount(String id, String oldUsername, String newUsername) thr
renameObject(DummyAccount.class, accounts, id, oldUsername, newUsername);
}
- public String addGroup(DummyGroup newGroup) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException {
+ public String addGroup(DummyGroup newGroup) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException, SchemaViolationException {
return addObject(groups, newGroup);
}
@@ -639,7 +657,7 @@ public void renameGroup(String id, String oldName, String newName) throws Object
renameObject(DummyGroup.class, groups, id, oldName, newName);
}
- public String addPrivilege(DummyPrivilege newGroup) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException {
+ public String addPrivilege(DummyPrivilege newGroup) throws ObjectAlreadyExistsException, ConnectException, FileNotFoundException, SchemaViolationException {
return addObject(privileges, newGroup);
}
@@ -692,6 +710,7 @@ public void runScript(String language, String scriptCode, Map pa
public void populateWithDefaultSchema() {
accountObjectClass.clear();
accountObjectClass.addAttributeDefinition(DummyAccount.ATTR_FULLNAME_NAME, String.class, true, false);
+ accountObjectClass.addAttributeDefinition(DummyAccount.ATTR_INTERNAL_ID, String.class, false, false);
accountObjectClass.addAttributeDefinition(DummyAccount.ATTR_DESCRIPTION_NAME, String.class, false, false);
accountObjectClass.addAttributeDefinition(DummyAccount.ATTR_INTERESTS_NAME, String.class, false, true);
accountObjectClass.addAttributeDefinition(DummyAccount.ATTR_PRIVILEGES_NAME, String.class, false, true);
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java
index 8053df1baf3..2715a86f8ca 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensUtil.java
@@ -595,7 +595,7 @@ public static void loadFullAccount(LensContext context
// already loaded
return;
}
- if (accCtx.isAdd()) {
+ if (accCtx.isAdd() && accCtx.getOid() == null) {
// nothing to load yet
return;
}
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java
index 8eaf23a22aa..c8c29906a8a 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java
@@ -215,6 +215,7 @@ private void processAssignmentsProjectionsWithFocus(LensCo
LOGGER.trace("Current assignments {}", SchemaDebugUtil.prettyPrint(assignmentsCurrent));
LOGGER.trace("Changed assignments {}", SchemaDebugUtil.prettyPrint(changedAssignments));
+// ObjectType source = determineSource(focusContext);
ObjectType source = null;
if (focusContext.getObjectCurrent() != null) {
source = focusContext.getObjectCurrent().asObjectable();
@@ -635,6 +636,20 @@ private void processAssignmentsProjectionsWithFocus(LensCo
}
+ private ObjectType determineSource(LensFocusContext focusContext)
+ throws SchemaException {
+ ObjectDelta delta = focusContext.getWaveDelta(focusContext.getLensContext().getExecutionWave());
+ if (delta != null && !delta.isEmpty()) {
+ return focusContext.getObjectNew().asObjectable();
+ }
+
+ if (focusContext.getObjectCurrent() != null) {
+ return focusContext.getObjectCurrent().asObjectable();
+ }
+
+ return focusContext.getObjectNew().asObjectable();
+ }
+
private void collectToZero(DeltaSetTriple> evaluatedAssignmentTriple,
EvaluatedAssignment evaluatedAssignment, boolean forceRecon) {
evaluatedAssignment.setForceRecon(forceRecon);
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
index 1c0fe8abc9c..87d98aeda4e 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
@@ -30,6 +30,7 @@
import com.evolveum.midpoint.common.Clock;
import com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator;
import com.evolveum.midpoint.model.api.PolicyViolationException;
+import com.evolveum.midpoint.model.api.context.ModelState;
import com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
@@ -406,15 +407,20 @@ public boolean checkDependencies(LensContext context,
|| strictness == ResourceObjectTypeDependencyStrictnessType.RELAXED) {
if (wasProvisioned(dependencyAccountContext, context.getExecutionWave())) {
// everything OK
- if (ResourceTypeUtil.isForceLoadDependentShadow(dependency) && !dependencyAccountContext.isFullShadow()){
- try {
- LensUtil.loadFullAccount(context, dependencyAccountContext, provisioningService, result);
- } catch (ObjectNotFoundException | CommunicationException | SchemaException
- | ConfigurationException | SecurityViolationException e) {
- // this is not fatal error. we can continue without full account..the incosinstencies will be treaten later, by reconciliation
- LOGGER.warn("Could not load dependent shadow, continue with the shadow loaded before.");
- }
- }
+// if (ResourceTypeUtil.isForceLoadDependentShadow(dependency) && !dependencyAccountContext.isDelete()){
+// LOGGER.info("FORCE TO LOAD FULL ACCOUNT " + dependencyAccountContext);
+// try {
+// LensUtil.loadFullAccount(context, dependencyAccountContext, provisioningService, result);
+// dependencyAccountContext.setDoReconciliation(true);
+// if (dependencyAccountContext.getExecutedDeltas() != null && !dependencyAccountContext.getExecutedDeltas().isEmpty()){
+// context.resetProjectionWave();
+// }
+// } catch (ObjectNotFoundException | CommunicationException | SchemaException
+// | ConfigurationException | SecurityViolationException e) {
+// // this is not fatal error. we can continue without full account..the incosinstencies will be treaten later, by reconciliation
+// LOGGER.warn("Could not load dependent shadow, continue with the shadow loaded before.");
+// }
+// }
} else {
// We do not want to throw exception here. That will stop entire projection.
// Let's just mark the projection as broken and skip it.
@@ -434,6 +440,45 @@ public boolean checkDependencies(LensContext context,
return true;
}
+ public void preprocessDependencies(LensContext context){
+
+ //in the first wave we do not have enougth information to preprocess connetxts
+ if (context.getExecutionWave() == 0){
+ return;
+ }
+
+ for (LensProjectionContext projContext : context.getProjectionContexts()){
+
+ for (ResourceObjectTypeDependencyType dependency: projContext.getDependencies()) {
+ ResourceShadowDiscriminator refRat = new ResourceShadowDiscriminator(dependency,
+ projContext.getResource().getOid(), projContext.getKind());
+ LOGGER.trace("LOOKING FOR {}", refRat);
+ LensProjectionContext dependencyAccountContext = context.findProjectionContext(refRat);
+ ResourceObjectTypeDependencyStrictnessType strictness = ResourceTypeUtil.getDependencyStrictness(dependency);
+ if (dependencyAccountContext != null){
+ // We have the context of the object that we depend on. We need to check if it was provisioned.
+ if (strictness == ResourceObjectTypeDependencyStrictnessType.STRICT
+ || strictness == ResourceObjectTypeDependencyStrictnessType.RELAXED) {
+ if (wasExecuted(dependencyAccountContext)) {
+ // everything OK
+ if (ResourceTypeUtil.isForceLoadDependentShadow(dependency) && !dependencyAccountContext.isDelete()){
+ LOGGER.info("FORCE TO LOAD FULL ACCOUNT " + dependencyAccountContext);
+ dependencyAccountContext.setDoReconciliation(true);
+ projContext.setDoReconciliation(true);
+// if (dependencyAccountContext.getExecutedDeltas() != null && !dependencyAccountContext.getExecutedDeltas().isEmpty()){
+// if (context.getProjectionWave() < context.getExecutionWave()){
+// context.resetProjectionWave();
+// }
+// }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ }
+
/**
* Finally checks for all the dependencies. Some dependencies cannot be checked during wave computations as
* we might not have all activation decisions yet.
@@ -484,14 +529,18 @@ private boolean wasProvisioned(LensProjectionContext acco
|| accountContext.getSynchronizationPolicyDecision() == SynchronizationPolicyDecision.IGNORE) {
return false;
}
+
+
PrismObject objectCurrent = accountContext.getObjectCurrent();
if (objectCurrent != null && objectCurrent.asObjectable().getFailedOperationType() != null) {
// There is unfinished operation in the shadow. We cannot continue.
return false;
- }
+ }
+
if (accountContext.isExists()) {
return true;
}
+
if (accountContext.isAdd()) {
List> executedDeltas = accountContext.getExecutedDeltas();
if (executedDeltas == null || executedDeltas.isEmpty()) {
@@ -505,8 +554,24 @@ private boolean wasProvisioned(LensProjectionContext acco
}
return true;
}
+
return false;
}
+
+ private boolean wasExecuted(LensProjectionContext accountContext){
+ if (accountContext.isAdd()) {
+
+ if (accountContext.getOid() == null){
+ return false;
+ }
+
+ List> executedDeltas = accountContext.getExecutedDeltas();
+ if (executedDeltas == null || executedDeltas.isEmpty()) {
+ return false;
+ }
+ }
+ return true;
+ }
class DependencyAndSource {
ResourceObjectTypeDependencyType dependency;
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java
index 65b2cad2fa6..b322d04c870 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/Projector.java
@@ -152,12 +152,15 @@ public void project(LensContext context, String activi
LOGGER.trace("WAVE: Starting the waves.");
context.setProjectionWave(0);
while (context.getProjectionWave() < maxWaves) {
-
+
context.checkAbortRequested();
LOGGER.trace("WAVE {} (maxWaves={}, executionWave={})", new Object[]{
context.getProjectionWave(), maxWaves, context.getExecutionWave()});
+ //just make sure everythink is loaded and set as needed
+ dependencyProcessor.preprocessDependencies(context);
+
// Process the focus-related aspects of the context. That means inbound, focus activation,
// object template and assignments.
focusProcessor.processFocus(context, activityDescription, now, task, result);
diff --git a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java
index afbb3e95935..2d3953105c4 100644
--- a/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java
+++ b/model/model-test/src/main/java/com/evolveum/midpoint/model/test/AbstractModelIntegrationTest.java
@@ -2189,6 +2189,15 @@ protected void assertDummyAccountAttribute(String dummyInstanceName, String user
}
}
}
+
+ protected void assertDummyAccountAttributeGenerated(String dummyInstanceName, String username) {
+ DummyAccount account = getDummyAccount(dummyInstanceName, username);
+ assertNotNull("No dummy account for username "+username, account);
+ Integer generated = account.getAttributeValue(DummyAccount.ATTR_INTERNAL_ID, Integer.class);
+ if (generated == null) {
+ AssertJUnit.fail("No value in generated attribute dir of " + dummyInstanceName + " dummy account " + username);
+ }
+ }
protected DummyGroup getDummyGroup(String dummyInstanceName, String name) {
DummyResource dummyResource = DummyResource.getInstance(dummyInstanceName);
diff --git a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java
index 795fe002511..c1eb84f3617 100644
--- a/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java
+++ b/repo/repo-test-util/src/main/java/com/evolveum/midpoint/test/DummyResourceContoller.java
@@ -239,7 +239,7 @@ public void assertDummyResourceSchemaSanityExtended(ResourceSchema resourceSchem
assertDummyResourceSchemaSanity(resourceSchema, resourceType);
ObjectClassComplexTypeDefinition accountDef = resourceSchema.findDefaultObjectClassDefinition(ShadowKindType.ACCOUNT);
- assertEquals("Unexpected number of defnitions", 16, accountDef.getDefinitions().size());
+ assertEquals("Unexpected number of defnitions", 17, accountDef.getDefinitions().size());
ResourceAttributeDefinition treasureDef = accountDef.findAttributeDefinition(DUMMY_ACCOUNT_ATTRIBUTE_TREASURE_NAME);
assertFalse("Treasure IS returned by default and should not be", treasureDef.isReturnedByDefault());
}
diff --git a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestTrafo.java b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestTrafo.java
index ffa425662f0..25c0b51ebb0 100644
--- a/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestTrafo.java
+++ b/testing/story/src/test/java/com/evolveum/midpoint/testing/story/TestTrafo.java
@@ -127,6 +127,7 @@ public class TestTrafo extends AbstractStoryTest {
public static final String NS_TRAFO_EXT = "http://midpoint.evolveum.com/xml/ns/story/trafo/ext";
private static final File TRAFO_SCHEMA_EXTENSION_FILE = new File(TEST_DIR, "extension.xsd");
private static final QName TRAFO_EXTENSION_HOMEDIR_QNAME = new QName(NS_TRAFO_EXT, "homedir");
+ private static final QName TRAFO_EXTENSION_UID_QNAME = new QName(NS_TRAFO_EXT, "uid");
private static final ItemPath TRAFO_EXTENSION_HOMEDIR_PATH = new ItemPath(UserType.F_EXTENSION, TRAFO_EXTENSION_HOMEDIR_QNAME);
private static final String TRAFO_MAIL_DOMAIN = "trafo.xx";
@@ -232,6 +233,7 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti
dummyResourceCtlAd.setResource(resourceDummyAd);
dummyResourceCtlMail = DummyResourceContoller.create(RESOURCE_DUMMY_MAIL_ID, resourceDummyMail);
+ dummyResourceCtlMail.populateWithDefaultSchema();
DummyObjectClass dummyAdAccountObjectClass = dummyResourceCtlMail.getDummyResource().getAccountObjectClass();
dummyResourceCtlMail.addAttrDef(dummyAdAccountObjectClass, DUMMY_ACCOUNT_ATTRIBUTE_MAIL_FIRST_NAME_NAME, String.class, false, false);
dummyResourceCtlMail.addAttrDef(dummyAdAccountObjectClass, DUMMY_ACCOUNT_ATTRIBUTE_MAIL_LAST_NAME_NAME, String.class, false, false);
@@ -622,7 +624,7 @@ public void test129JackAccountMailGone() throws Exception {
display("Audit", dummyAuditService);
dummyAuditService.assertRecords(2);
dummyAuditService.assertSimpleRecordSanity();
- dummyAuditService.assertExecutionDeltas(2);
+ dummyAuditService.assertExecutionDeltas(3);
dummyAuditService.asserHasDelta(ChangeType.MODIFY, UserType.class);
dummyAuditService.asserHasDelta(ChangeType.DELETE, ShadowType.class);
dummyAuditService.assertExecutionSuccess();
@@ -692,6 +694,7 @@ public void test150JackAssignRoleEmployee() throws Exception {
assertDummyAccountAttribute(RESOURCE_DUMMY_AD_ID, ACCOUNT_JACK_AD_DN,
DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_AD_TELEPHONE_NUMBER_NAME, "555-1234");
+
// MAIL ACCOUNT
// Check shadow
@@ -724,11 +727,18 @@ public void test150JackAssignRoleEmployee() throws Exception {
DUMMY_ACCOUNT_ATTRIBUTE_MAIL_MAIL_FILE_NAME_NAME, "mail\\"+USER_JACK_USERNAME);
assertDummyAccountAttribute(RESOURCE_DUMMY_MAIL_ID, ACCOUNT_JACK_MAIL_USERNAME,
DUMMY_ACCOUNT_ATTRIBUTE_MAIL_MAIL_DOMAIN_NAME, "TRAFO");
-
+ assertDummyAccountAttributeGenerated(RESOURCE_DUMMY_MAIL_ID, ACCOUNT_JACK_MAIL_USERNAME);
+
+ PrismProperty generatedValue = userJack.findExtensionItem(TRAFO_EXTENSION_UID_QNAME);
+ assertNotNull("Generated id value must not be null", generatedValue);
+
// Set by inbound mappings
PrismAsserts.assertPropertyValue(userJack, UserType.F_EMAIL_ADDRESS, "Jack.Sparrow@" + TRAFO_MAIL_DOMAIN);
PrismAsserts.assertPropertyValue(userJack,
new ItemPath(UserType.F_EXTENSION, TRAFO_EXTENSION_HOMEDIR_QNAME), "c:\\install\\test-id-folder");
+ // set to AD from mail resource - attribute was generated by mail resource and synced to the AD
+ assertDummyAccountAttribute(RESOURCE_DUMMY_AD_ID, ACCOUNT_JACK_AD_DN,
+ DummyResourceContoller.DUMMY_ACCOUNT_ATTRIBUTE_AD_DESCRIPTION_NAME, String.valueOf(generatedValue.getRealValue()));
// Check audit
display("Audit", dummyAuditService);
@@ -738,7 +748,7 @@ public void test150JackAssignRoleEmployee() throws Exception {
dummyAuditService.assertExecutionDeltas(0,3);
dummyAuditService.asserHasDelta(0,ChangeType.MODIFY, UserType.class); // primary, link (2 deltas)
dummyAuditService.asserHasDelta(0,ChangeType.ADD, ShadowType.class); // AD account
- dummyAuditService.assertExecutionDeltas(1,2);
+ dummyAuditService.assertExecutionDeltas(1,3);
dummyAuditService.asserHasDelta(1,ChangeType.MODIFY, UserType.class); // link
dummyAuditService.asserHasDelta(1,ChangeType.ADD, ShadowType.class); // Mail account
dummyAuditService.assertExecutionDeltas(2,2);
diff --git a/testing/story/src/test/resources/schema/trafo.xsd b/testing/story/src/test/resources/schema/trafo.xsd
index 742e55353d7..5333780bacb 100644
--- a/testing/story/src/test/resources/schema/trafo.xsd
+++ b/testing/story/src/test/resources/schema/trafo.xsd
@@ -37,6 +37,13 @@
+
+
+
+ true
+
+
+
diff --git a/testing/story/src/test/resources/trafo/resource-dummy-ad.xml b/testing/story/src/test/resources/trafo/resource-dummy-ad.xml
index 0ff09830624..db6dceedfe1 100644
--- a/testing/story/src/test/resources/trafo/resource-dummy-ad.xml
+++ b/testing/story/src/test/resources/trafo/resource-dummy-ad.xml
@@ -319,6 +319,15 @@ if (basic.stringify(employeeType) == 'T' || basic.stringify(employeeType) == 'R'
+
+
+
+
weak
@@ -377,6 +386,7 @@ midPoint -->
relaxed
10
+ true
10
diff --git a/testing/story/src/test/resources/trafo/resource-dummy-mail.xml b/testing/story/src/test/resources/trafo/resource-dummy-mail.xml
index 3a5cdd268c8..94792385537 100644
--- a/testing/story/src/test/resources/trafo/resource-dummy-mail.xml
+++ b/testing/story/src/test/resources/trafo/resource-dummy-mail.xml
@@ -48,6 +48,7 @@
mail
true
uuid
+ true
@@ -187,6 +188,16 @@ basic.norm(basic.stringify(familyName))?.replaceAll(/\w+/, { it[0].toUpperCase()
$user/familyName
+
+
+
+ [ri:internalId]
+ Generated ID by resource
+
+
+ $user/extension/trafo:uid
+
+
[ri:ShortName]
From c258841dfe04849e4b2fa8c35d7e0c6c3367a7a9 Mon Sep 17 00:00:00 2001
From: "Katarina Valalikova (katkav)"
Date: Thu, 2 Oct 2014 09:27:49 +0200
Subject: [PATCH 03/19] improving searching conflicting shadow (already exists
situation)
---
.../impl/ObjectAlreadyExistHandler.java | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
index 6f0375b0a92..400e58b1e88 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
@@ -17,6 +17,7 @@
package com.evolveum.midpoint.provisioning.consistency.impl;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import javax.xml.namespace.QName;
@@ -38,7 +39,9 @@
import com.evolveum.midpoint.provisioning.ucf.api.GenericFrameworkException;
import com.evolveum.midpoint.schema.ResultHandler;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
+import com.evolveum.midpoint.schema.processor.ResourceAttribute;
import com.evolveum.midpoint.schema.result.OperationResult;
+import com.evolveum.midpoint.schema.util.ShadowUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
@@ -120,8 +123,15 @@ public T handleError(T shadow, FailedOperation op, Except
private ObjectQuery createQueryByIcfName(ShadowType shadow) throws SchemaException {
// TODO: error handling TODO TODO TODO set matching rule instead of null in equlas filter
- PrismProperty nameProperty = shadow.getAttributes().asPrismContainerValue()
- .findProperty(new QName(SchemaConstants.NS_ICF_SCHEMA, "name"));
+ Collection> secondaryIdentifiers = ShadowUtil.getSecondaryIdentifiers(shadow);
+ PrismProperty nameProperty = null;
+ if (secondaryIdentifiers.size() != 1){
+ nameProperty = shadow.getAttributes().asPrismContainerValue()
+ .findProperty(new QName(SchemaConstants.NS_ICF_SCHEMA, "name"));
+ } else {
+ nameProperty = secondaryIdentifiers.iterator().next();
+ }
+
EqualFilter nameFilter = EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, nameProperty.getDefinition().getName()),nameProperty);
RefFilter resourceRefFilter = RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class,
prismContext, shadow.getResourceRef().getOid());
From fefc840422692d46008d366dcd7f8973ec2d5cc8 Mon Sep 17 00:00:00 2001
From: Erik Suta
Date: Thu, 2 Oct 2014 14:22:19 +0200
Subject: [PATCH 04/19] Adding tooltip information to dumpInterval input field
- shows value type (minutes)
---
.../component/LoggingConfigPanel.html | 2 +
.../component/LoggingConfigPanel.java | 48 ++++++++++---------
.../component/LoggingConfigPanel.properties | 2 +
.../component/SystemConfigPanel.java | 3 --
4 files changed, 29 insertions(+), 26 deletions(-)
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.html
index 69890a0cde0..7e69a3c32e1 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.html
@@ -120,6 +120,8 @@
+
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.java
index f6a022a1894..c0eda5b04da 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/LoggingConfigPanel.java
@@ -20,7 +20,6 @@
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.web.component.AjaxButton;
-import com.evolveum.midpoint.web.component.DropDownMultiChoice;
import com.evolveum.midpoint.web.component.data.TablePanel;
import com.evolveum.midpoint.web.component.data.column.*;
import com.evolveum.midpoint.web.component.input.DropDownChoicePanel;
@@ -31,8 +30,8 @@
import com.evolveum.midpoint.web.component.util.ListDataProvider;
import com.evolveum.midpoint.web.component.util.LoadableModel;
import com.evolveum.midpoint.web.component.util.SimplePanel;
-import com.evolveum.midpoint.web.page.admin.configuration.PageSystemConfiguration;
import com.evolveum.midpoint.web.page.admin.configuration.dto.*;
+import com.evolveum.midpoint.web.util.InfoTooltipBehavior;
import com.evolveum.midpoint.web.util.WebMiscUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
@@ -45,13 +44,12 @@
import org.apache.wicket.behavior.AttributeAppender;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
+import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.*;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
-import org.w3c.dom.html.HTMLTableElement;
-
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -64,7 +62,6 @@ public class LoggingConfigPanel extends SimplePanel {
private static final String DOT_CLASS = LoggingConfigPanel.class.getName() + ".";
private static final String OPERATION_LOAD_LOGGING_CONFIGURATION = DOT_CLASS + "loadLoggingConfiguration";
- private static final String OPERATION_UPDATE_LOGGING_CONFIGURATION = DOT_CLASS + "updateLoggingConfiguration";
private static final String ID_LOGGERS_TABLE = "loggersTable";
private static final String ID_ROOT_LEVEL = "rootLevel";
@@ -74,6 +71,7 @@ public class LoggingConfigPanel extends SimplePanel {
private static final String ID_BUTTON_ADD_FILE_APPENDER = "addFileAppender";
private static final String ID_BUTTON_DELETE_APPENDER = "deleteAppender";
private static final String ID_BUTTON_ADD_STANDARD_LOGGER = "addStandardLogger";
+ private static final String ID_DUMP_INTERVAL_TOOLTIP = "dumpIntervalTooltip";
public LoggingConfigPanel(String id) {
super(id, null);
@@ -130,9 +128,9 @@ protected void initLayout() {
private void initLoggers() {
initRoot();
- ISortableDataProvider provider = new ListDataProvider(this,
+ ISortableDataProvider provider = new ListDataProvider<>(this,
new PropertyModel>(getModel(), "loggers"));
- TablePanel table = new TablePanel(ID_LOGGERS_TABLE, provider, initLoggerColumns());
+ TablePanel table = new TablePanel<>(ID_LOGGERS_TABLE, provider, initLoggerColumns());
table.setOutputMarkupId(true);
table.setShowPaging(false);
add(table);
@@ -181,13 +179,13 @@ public void onClick(AjaxRequestTarget target) {
}
private void initRoot() {
- DropDownChoice rootLevel = new DropDownChoice(ID_ROOT_LEVEL,
+ DropDownChoice rootLevel = new DropDownChoice<>(ID_ROOT_LEVEL,
new PropertyModel(getModel(), LoggingDto.F_ROOT_LEVEL),
WebMiscUtil.createReadonlyModelFromEnum(LoggingLevelType.class));
add(rootLevel);
- DropDownChoice rootAppender = new DropDownChoice(ID_ROOT_APPENDER,
+ DropDownChoice rootAppender = new DropDownChoice<>(ID_ROOT_APPENDER,
new PropertyModel(getModel(), LoggingDto.F_ROOT_APPENDER), createAppendersListModel());
rootAppender.setNullValid(true);
rootAppender.add(new OnChangeAjaxBehavior() {
@@ -207,7 +205,7 @@ private void initAudit(){
CheckBox auditDetails = new CheckBox("auditDetails", new PropertyModel(getModel(), "auditDetails"));
add(auditDetails);
- DropDownChoice auditAppender = new DropDownChoice("auditAppender", new PropertyModel(
+ DropDownChoice auditAppender = new DropDownChoice<>("auditAppender", new PropertyModel(
getModel(), "auditAppender"), createAppendersListModel());
auditAppender.setNullValid(true);
add(auditAppender);
@@ -215,13 +213,13 @@ private void initAudit(){
private void initProfiling(){
//Entry-Exit profiling init
- DropDownChoice profilingLevel = new DropDownChoice("profilingLevel",
+ DropDownChoice profilingLevel = new DropDownChoice<>("profilingLevel",
new PropertyModel(getModel(), "profilingLevel"),
WebMiscUtil.createReadonlyModelFromEnum(ProfilingLevel.class),
- new EnumChoiceRenderer(this));
+ new EnumChoiceRenderer(this));
add(profilingLevel);
- DropDownChoice profilingAppender = new DropDownChoice("profilingAppender",
+ DropDownChoice profilingAppender = new DropDownChoice<>("profilingAppender",
new PropertyModel(getModel(), "profilingAppender"), createAppendersListModel());
profilingAppender.setNullValid(true);
add(profilingAppender);
@@ -246,9 +244,13 @@ private void initProfiling(){
add(subsystemTaskManager);
add(subsystemWorkflow);
- TextField dumpInterval = new TextField("dumpInterval", new PropertyModel(getModel(),
+ TextField dumpInterval = new TextField<>("dumpInterval", new PropertyModel(getModel(),
"dumpInterval"));
add(dumpInterval);
+
+ Label dumpIntervalTooltip = new Label(ID_DUMP_INTERVAL_TOOLTIP);
+ dumpIntervalTooltip.add(new InfoTooltipBehavior());
+ add(dumpIntervalTooltip);
}
private void addStandardLoggerPerformed(AjaxRequestTarget target){
@@ -287,7 +289,7 @@ private TablePanel getAppendersTable(){
}
private List> initLoggerColumns() {
- List> columns = new ArrayList>();
+ List> columns = new ArrayList<>();
IColumn column = new CheckBoxHeaderColumn();
columns.add(column);
@@ -342,7 +344,7 @@ public String getIdValue(LoggingComponentType item, int index) {
return dropDownChoicePanel;
} else {
- TextPanel textPanel = new TextPanel(componentId, new PropertyModel(model, getPropertyExpression()));
+ TextPanel textPanel = new TextPanel<>(componentId, new PropertyModel(model, getPropertyExpression()));
FormComponent input = textPanel.getBaseFormComponent();
input.add(new AttributeAppender("style", "width: 100%"));
input.add(new EmptyOnBlurAjaxFormUpdatingBehaviour());
@@ -415,7 +417,7 @@ protected String load() {
@Override
protected InputPanel createInputPanel(String componentId, IModel model) {
IModel
+
+ Assignment
+
@@ -2518,6 +2522,7 @@
+ Assignment
@@ -2543,6 +2548,7 @@
tns:targetRef
+ Target
@@ -2552,6 +2558,9 @@
TODO: target ref
+
+ Target
+
@@ -2560,6 +2569,9 @@
TODO
+
+ Construction
+
@@ -2590,6 +2602,7 @@
tns:OrgType
+ Tenant reference
@@ -6084,6 +6097,9 @@
TODO
+
+ Inducement
+
diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java
index bae7a6ea59d..65a21f836d2 100644
--- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java
+++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/formatters/TextFormatter.java
@@ -20,6 +20,7 @@
import com.evolveum.midpoint.prism.*;
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.prism.path.NameItemPathSegment;
@@ -59,10 +60,25 @@ public class TextFormatter {
private static final Trace LOGGER = TraceManager.getTrace(TextFormatter.class);
public String formatObjectModificationDelta(ObjectDelta extends Objectable> objectDelta, List hiddenPaths, boolean showOperationalAttributes) {
+ return formatObjectModificationDelta(objectDelta, hiddenPaths, showOperationalAttributes, null, null);
+ }
+ // objectOld and objectNew are used for explaining changed container values, e.g. assignment[1]/tenantRef (see MID-2047)
+ // if null, they are ignored
+ public String formatObjectModificationDelta(ObjectDelta extends Objectable> objectDelta, List hiddenPaths, boolean showOperationalAttributes,
+ PrismObject objectOld, PrismObject objectNew) {
Validate.notNull(objectDelta, "objectDelta is null");
Validate.isTrue(objectDelta.isModify(), "objectDelta is not a modification delta");
+ PrismObjectDefinition objectDefinition;
+ if (objectNew != null && objectNew.getDefinition() != null) {
+ objectDefinition = objectNew.getDefinition();
+ } else if (objectOld != null && objectOld.getDefinition() != null) {
+ objectDefinition = objectOld.getDefinition();
+ } else {
+ objectDefinition = null;
+ }
+
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("formatObjectModificationDelta: objectDelta = " + objectDelta.debugDump() + ", hiddenPaths = " + PrettyPrinter.prettyPrint(hiddenPaths));
}
@@ -70,17 +86,68 @@ public String formatObjectModificationDelta(ObjectDelta extends Objectable> ob
StringBuilder retval = new StringBuilder();
List toBeDisplayed = filterAndOrderItemDeltas(objectDelta, hiddenPaths, showOperationalAttributes);
-
for (ItemDelta itemDelta : toBeDisplayed) {
retval.append(" - ");
- retval.append(getItemDeltaLabel(itemDelta));
+ retval.append(getItemDeltaLabel(itemDelta, objectDefinition));
retval.append(":\n");
formatItemDeltaContent(retval, itemDelta, hiddenPaths, showOperationalAttributes);
}
+ explainPaths(retval, toBeDisplayed, objectDefinition, objectOld, objectNew, hiddenPaths, showOperationalAttributes);
+
return retval.toString();
}
+ private void explainPaths(StringBuilder sb, List deltas, PrismObjectDefinition objectDefinition, PrismObject objectOld, PrismObject objectNew, List hiddenPaths, boolean showOperationalAttributes) {
+ if (objectOld == null && objectNew == null) {
+ return; // no data - no point in trying
+ }
+ boolean first = true;
+ List alreadyExplained = new ArrayList<>();
+ for (ItemDelta itemDelta : deltas) {
+ ItemPath pathToExplain = getPathToExplain(itemDelta);
+ if (pathToExplain == null || ItemPath.containsSubpathOrEquivalent(alreadyExplained, pathToExplain)) {
+ continue; // null or already processed
+ }
+ PrismObject source = null;
+ Object item = null;
+ if (objectNew != null) {
+ item = objectNew.find(pathToExplain);
+ source = objectNew;
+ }
+ if (item == null && objectOld != null) {
+ item = objectOld.find(pathToExplain);
+ source = objectOld;
+ }
+ if (item == null) {
+ LOGGER.warn("Couldn't find {} in {} nor {}, no explanation could be created.", new Object[] {pathToExplain, objectNew, objectOld});
+ continue;
+ }
+ if (first) {
+ sb.append("\nNotes:\n");
+ first = false;
+ }
+ String label = getItemPathLabel(pathToExplain, itemDelta.getDefinition(), objectDefinition);
+ // the item should be a PrismContainerValue
+ if (item instanceof PrismContainerValue) {
+ sb.append(" - ").append(label).append(":\n");
+ formatContainerValue(sb, " ", (PrismContainerValue) item, false, hiddenPaths, showOperationalAttributes);
+ } else {
+ LOGGER.warn("{} in {} was expected to be a PrismContainerValue; it is {} instead", new Object[]{pathToExplain, source, item.getClass()});
+ if (item instanceof PrismContainer) {
+ formatPrismContainer(sb, " ", (PrismContainer) item, false, hiddenPaths, showOperationalAttributes);
+ } else if (item instanceof PrismReference) {
+ formatPrismReference(sb, " ", (PrismReference) item, false);
+ } else if (item instanceof PrismProperty) {
+ formatPrismProperty(sb, " ", (PrismProperty) item);
+ } else {
+ sb.append("Unexpected item: ").append(item).append("\n");
+ }
+ }
+ alreadyExplained.add(pathToExplain);
+ }
+ }
+
private void formatItemDeltaContent(StringBuilder sb, ItemDelta itemDelta, List hiddenPaths, boolean showOperationalAttributes) {
formatItemDeltaValues(sb, "ADD", itemDelta.getValuesToAdd(), false, hiddenPaths, showOperationalAttributes);
formatItemDeltaValues(sb, "DELETE", itemDelta.getValuesToDelete(), true, hiddenPaths, showOperationalAttributes);
@@ -93,7 +160,9 @@ private void formatItemDeltaValues(StringBuilder sb, String type, Collection e
sb.append(" - " + type + ": ");
String prefix = " ";
formatPrismValue(sb, prefix, prismValue, mightBeRemoved, hiddenPaths, showOperationalAttributes);
- sb.append("\n");
+ if (!(prismValue instanceof PrismContainerValue)) { // container values already end with newline
+ sb.append("\n");
+ }
}
}
}
@@ -146,39 +215,12 @@ private void formatContainerValue(StringBuilder sb, String prefix, PrismContaine
List- toBeDisplayed = filterAndOrderItems(containerValue.getItems(), hiddenPaths, showOperationalAttributes);
for (Item item : toBeDisplayed) {
- sb.append(prefix);
- sb.append(" - ");
- sb.append(getItemLabel(item));
- sb.append(": ");
if (item instanceof PrismProperty) {
- if (item.size() > 1) {
- for (PrismPropertyValue propertyValue : ((PrismProperty extends Object>) item).getValues()) {
- sb.append("\n");
- sb.append(prefix + " - ");
- sb.append(ValueDisplayUtil.toStringValue(propertyValue));
- }
- } else if (item.size() == 1) {
- sb.append(ValueDisplayUtil.toStringValue(((PrismProperty extends Object>) item).getValue(0)));
- }
- sb.append("\n");
+ formatPrismProperty(sb, prefix, item);
} else if (item instanceof PrismReference) {
- if (item.size() > 1) {
- for (PrismReferenceValue referenceValue : ((PrismReference) item).getValues()) {
- sb.append("\n");
- sb.append(prefix + " - ");
- sb.append(formatReferenceValue(referenceValue, mightBeRemoved));
- }
- } else if (item.size() == 1) {
- sb.append(formatReferenceValue(((PrismReference) item).getValue(0), mightBeRemoved));
- }
- sb.append("\n");
+ formatPrismReference(sb, prefix, item, mightBeRemoved);
} else if (item instanceof PrismContainer) {
- for (PrismContainerValue subContainerValue : ((PrismContainer extends Containerable>) item).getValues()) {
- sb.append("\n");
- String prefixSubContainer = prefix + " ";
- formatContainerValue(sb, prefixSubContainer, subContainerValue, mightBeRemoved, hiddenPaths, showOperationalAttributes);
- }
- sb.append("\n");
+ formatPrismContainer(sb, prefix, item, mightBeRemoved, hiddenPaths, showOperationalAttributes);
} else {
sb.append("Unexpected Item type: ");
sb.append(item);
@@ -188,6 +230,54 @@ private void formatContainerValue(StringBuilder sb, String prefix, PrismContaine
}
}
+ private void formatPrismContainer(StringBuilder sb, String prefix, Item item, boolean mightBeRemoved, List hiddenPaths, boolean showOperationalAttributes) {
+ for (PrismContainerValue subContainerValue : ((PrismContainer extends Containerable>) item).getValues()) {
+ sb.append(prefix);
+ sb.append(" - ");
+ sb.append(getItemLabel(item));
+ if (subContainerValue.getId() != null) {
+ sb.append(" #").append(subContainerValue.getId());
+ }
+ sb.append(":\n");
+ String prefixSubContainer = prefix + " ";
+ formatContainerValue(sb, prefixSubContainer, subContainerValue, mightBeRemoved, hiddenPaths, showOperationalAttributes);
+ }
+ }
+
+ private void formatPrismReference(StringBuilder sb, String prefix, Item item, boolean mightBeRemoved) {
+ sb.append(prefix);
+ sb.append(" - ");
+ sb.append(getItemLabel(item));
+ sb.append(": ");
+ if (item.size() > 1) {
+ for (PrismReferenceValue referenceValue : ((PrismReference) item).getValues()) {
+ sb.append("\n");
+ sb.append(prefix + " - ");
+ sb.append(formatReferenceValue(referenceValue, mightBeRemoved));
+ }
+ } else if (item.size() == 1) {
+ sb.append(formatReferenceValue(((PrismReference) item).getValue(0), mightBeRemoved));
+ }
+ sb.append("\n");
+ }
+
+ private void formatPrismProperty(StringBuilder sb, String prefix, Item item) {
+ sb.append(prefix);
+ sb.append(" - ");
+ sb.append(getItemLabel(item));
+ sb.append(": ");
+ if (item.size() > 1) {
+ for (PrismPropertyValue propertyValue : ((PrismProperty extends Object>) item).getValues()) {
+ sb.append("\n");
+ sb.append(prefix + " - ");
+ sb.append(ValueDisplayUtil.toStringValue(propertyValue));
+ }
+ } else if (item.size() == 1) {
+ sb.append(ValueDisplayUtil.toStringValue(((PrismProperty extends Object>) item).getValue(0)));
+ }
+ sb.append("\n");
+ }
+
private String formatReferenceValue(PrismReferenceValue value, boolean mightBeRemoved) {
OperationResult result = new OperationResult("dummy");
@@ -255,21 +345,62 @@ private String localPart(QName qname) {
}
// we call this on filtered list of item deltas - all of they have definition set
- private String getItemDeltaLabel(ItemDelta itemDelta) {
- if (itemDelta.getDefinition().getDisplayName() != null) {
- return itemDelta.getDefinition().getDisplayName();
- } else {
- String retval = "";
- for (ItemPathSegment segment : itemDelta.getPath().getSegments()) {
- if (segment instanceof NameItemPathSegment) {
- if (!retval.isEmpty()) {
- retval += "/";
- }
- retval += ((NameItemPathSegment) segment).getName().getLocalPart();
- }
+ private String getItemDeltaLabel(ItemDelta itemDelta, PrismObjectDefinition objectDefinition) {
+ return getItemPathLabel(itemDelta.getPath(), itemDelta.getDefinition(), objectDefinition);
+ }
+
+ private String getItemPathLabel(ItemPath path, Definition deltaDefinition, PrismObjectDefinition objectDefinition) {
+
+ NameItemPathSegment lastNamedSegment = path.lastNamed();
+
+ StringBuilder sb = new StringBuilder();
+ for (ItemPathSegment segment : path.getSegments()) {
+ if (segment instanceof NameItemPathSegment) {
+ if (sb.length() > 0) {
+ sb.append("/");
+ }
+ Definition itemDefinition;
+ if (objectDefinition == null) {
+ if (segment == lastNamedSegment) { // definition for last segment is the definition taken from delta
+ itemDefinition = deltaDefinition; // this may be null but we don't care
+ } else {
+ itemDefinition = null; // definitions for previous segments are unknown
+ }
+ } else {
+ // todo we could make this iterative (resolving definitions while walking down the path); but this is definitely simpler to implement and debug :)
+ itemDefinition = objectDefinition.findItemDefinition(path.allUpToIncluding(segment));
+ }
+ if (itemDefinition != null && itemDefinition.getDisplayName() != null) {
+ sb.append(itemDefinition.getDisplayName());
+ } else {
+ sb.append(((NameItemPathSegment) segment).getName().getLocalPart());
+ }
+ } else if (segment instanceof IdItemPathSegment) {
+ sb.append("[").append(((IdItemPathSegment) segment).getId()).append("]");
}
- return retval;
}
+ return sb.toString();
+ }
+
+ // we call this on filtered list of item deltas - all of they have definition set
+ private ItemPath getPathToExplain(ItemDelta itemDelta) {
+ ItemPath path = itemDelta.getPath();
+
+ for (int i = 0; i < path.size(); i++) {
+ ItemPathSegment segment = path.getSegments().get(i);
+ if (segment instanceof IdItemPathSegment) {
+ if (i < path.size()-1 || itemDelta.isDelete()) {
+ return path.allUpToIncluding(i);
+ } else {
+ // this means that the path ends with [id] segment *and* the value(s) are
+ // only added and deleted, i.e. they are shown in the delta anyway
+ // (actually it is questionable whether path in delta can end with [id] segment,
+ // but we test for this case just to be sure)
+ return null;
+ }
+ }
+ }
+ return null;
}
private List filterAndOrderItemDeltas(ObjectDelta extends Objectable> objectDelta, List hiddenPaths, boolean showOperationalAttributes) {
@@ -302,7 +433,7 @@ public int compare(ItemDelta delta1, ItemDelta delta2) {
return toBeDisplayed;
}
- // we call this on filtered list of items - all of they have definition set
+ // we call this on filtered list of items - all of them have definition set
private String getItemLabel(Item item) {
return item.getDefinition().getDisplayName() != null ?
item.getDefinition().getDisplayName() : item.getElementName().getLocalPart();
diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java
index a5915d3ffc3..9b2d3dd59de 100644
--- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java
+++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java
@@ -161,7 +161,7 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S
body.append("\n");
} else if (delta.isModify()) {
body.append("The ").append(typeNameLower).append(" record was " + attemptedTo + "modified. Modified attributes are:\n");
- body.append(textFormatter.formatObjectModificationDelta(delta, hiddenPaths, isWatchAuxiliaryAttributes(generalNotifierType)));
+ body.append(textFormatter.formatObjectModificationDelta(delta, hiddenPaths, isWatchAuxiliaryAttributes(generalNotifierType), focusContext.getObjectOld(), focusContext.getObjectNew()));
body.append("\n");
} else if (delta.isDelete()) {
body.append("The ").append(typeNameLower).append(" record was " + attemptedTo + "removed.\n\n");
diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java
index e589e1460d3..717458aa6fb 100644
--- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java
+++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleResourceObjectNotifier.java
@@ -185,7 +185,10 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S
}
if (resourceObjectEvent.getOperationStatus() != OperationStatus.IN_PROGRESS) {
- body.append(textFormatter.formatObjectModificationDelta(delta, hiddenPaths, isWatchAuxiliaryAttributes(generalNotifierType)));
+ // todo we do not have objectOld + objectNew, only the current status
+ // it is used to explain modified containers with identifiers -- however, currently I don't know of use of such containers in shadows, which would be visible in notifications
+ body.append(textFormatter.formatObjectModificationDelta(delta, hiddenPaths, isWatchAuxiliaryAttributes(generalNotifierType),
+ resourceObjectEvent.getAccountOperationDescription().getCurrentShadow(), null));
} else {
// special case - here the attributes are 'result', 'failedOperationType', 'objectChange', 'attemptNumber'
// we have to unwrap attributes that are to be modified from the objectChange item
@@ -206,7 +209,8 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S
deltas.add((ObjectDelta) DeltaConvertor.createObjectDelta(change.getValue(), prismContext));
}
ObjectDelta shadowDelta = ObjectDelta.summarize(deltas);
- body.append(textFormatter.formatObjectModificationDelta(shadowDelta, hiddenPaths, isWatchAuxiliaryAttributes(generalNotifierType)));
+ body.append(textFormatter.formatObjectModificationDelta(shadowDelta, hiddenPaths, isWatchAuxiliaryAttributes(generalNotifierType),
+ resourceObjectEvent.getAccountOperationDescription().getCurrentShadow(), null));
} catch (SchemaException e) {
LoggingUtils.logException(LOGGER, "Unable to determine the shadow change; operation = {}", e, resourceObjectEvent.getAccountOperationDescription().debugDump());
body.append("(unable to determine the change because of schema exception: ").append(e.getMessage()).append(")\n");
diff --git a/model/notifications-impl/src/test/java/com/evolveum/midpoint/notifications/impl/TestTextFormatter.java b/model/notifications-impl/src/test/java/com/evolveum/midpoint/notifications/impl/TestTextFormatter.java
index bdeb20a6d27..1f60579dce2 100644
--- a/model/notifications-impl/src/test/java/com/evolveum/midpoint/notifications/impl/TestTextFormatter.java
+++ b/model/notifications-impl/src/test/java/com/evolveum/midpoint/notifications/impl/TestTextFormatter.java
@@ -32,6 +32,9 @@
import java.util.Arrays;
import java.util.List;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
/**
* @author mederly
*/
@@ -91,7 +94,7 @@ public void setup() throws SchemaException, SAXException, IOException {
}
- @Test(enabled = false)
+ @Test(enabled = true)
public void test010FormatUser() throws Exception {
// GIVEN
@@ -114,71 +117,92 @@ public void test010FormatUser() throws Exception {
// THEN
- AssertJUnit.assertTrue("hidden operational attribute when it should be shown ('hide none')", jackFormattedHideNone.contains("createTimestamp:"));
- AssertJUnit.assertTrue("hidden auxiliary attribute (effective status) when it should be shown ('hide none')", jackFormattedHideNone.contains("Effective Status: ENABLED"));
- AssertJUnit.assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide none')", jackFormattedHideNone.contains("Family Name: Sparrow"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide none')", jackFormattedHideNone.contains("ship: Black Pearl"));
+ assertTrue("hidden operational attribute when it should be shown ('hide none')", jackFormattedHideNone.contains("createTimestamp:"));
+ assertTrue("hidden auxiliary attribute (effective status) when it should be shown ('hide none')", jackFormattedHideNone.contains("Effective Status: ENABLED"));
+ assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide none')", jackFormattedHideNone.contains("Family Name: Sparrow"));
+ assertTrue("hidden standard attribute when it should be shown ('hide none')", jackFormattedHideNone.contains("ship: Black Pearl"));
- AssertJUnit.assertTrue("shown operational attribute when it should be hidden ('hide oper')", !jackFormattedHideOper.contains("createTimestamp:"));
- AssertJUnit.assertTrue("hidden auxiliary attribute when it should be shown ('hide oper')", jackFormattedHideOper.contains("Effective Status: ENABLED"));
- AssertJUnit.assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide oper')", jackFormattedHideOper.contains("Family Name: Sparrow"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide oper')", jackFormattedHideOper.contains("ship: Black Pearl"));
+ assertTrue("shown operational attribute when it should be hidden ('hide oper')", !jackFormattedHideOper.contains("createTimestamp:"));
+ assertTrue("hidden auxiliary attribute when it should be shown ('hide oper')", jackFormattedHideOper.contains("Effective Status: ENABLED"));
+ assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide oper')", jackFormattedHideOper.contains("Family Name: Sparrow"));
+ assertTrue("hidden standard attribute when it should be shown ('hide oper')", jackFormattedHideOper.contains("ship: Black Pearl"));
- AssertJUnit.assertTrue("shown auxiliary attribute (metadata) when it should be hidden ('hide aux')", !jackFormattedHideAux.contains("createTimestamp:"));
- AssertJUnit.assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux')", !jackFormattedHideAux.contains("Family Name: Sparrow"));
- AssertJUnit.assertTrue("shown auxiliary attribute (effective status) when it should be hidden ('hide aux')", !jackFormattedHideAux.contains("Effective Status: ENABLED"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide aux')", jackFormattedHideAux.contains("ship: Black Pearl"));
+ assertTrue("shown auxiliary attribute (metadata) when it should be hidden ('hide aux')", !jackFormattedHideAux.contains("createTimestamp:"));
+ assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux')", !jackFormattedHideAux.contains("Family Name: Sparrow"));
+ assertTrue("shown auxiliary attribute (effective status) when it should be hidden ('hide aux')", !jackFormattedHideAux.contains("Effective Status: ENABLED"));
+ assertTrue("hidden standard attribute when it should be shown ('hide aux')", jackFormattedHideAux.contains("ship: Black Pearl"));
- AssertJUnit.assertTrue("shown operational attribute when it should be hidden ('hide aux and oper')", !jackFormattedHideAuxAndOper.contains("createTimestamp:"));
- AssertJUnit.assertTrue("shown auxiliary attribute (effective status) when it should be hidden ('hide aux and oper')", !jackFormattedHideAuxAndOper.contains("Effective Status: ENABLED"));
- AssertJUnit.assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux and oper')", !jackFormattedHideAuxAndOper.contains("Family Name: Sparrow"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide aux and oper')", jackFormattedHideAuxAndOper.contains("ship: Black Pearl"));
+ assertTrue("shown operational attribute when it should be hidden ('hide aux and oper')", !jackFormattedHideAuxAndOper.contains("createTimestamp:"));
+ assertTrue("shown auxiliary attribute (effective status) when it should be hidden ('hide aux and oper')", !jackFormattedHideAuxAndOper.contains("Effective Status: ENABLED"));
+ assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux and oper')", !jackFormattedHideAuxAndOper.contains("Family Name: Sparrow"));
+ assertTrue("hidden standard attribute when it should be shown ('hide aux and oper')", jackFormattedHideAuxAndOper.contains("ship: Black Pearl"));
}
- @Test(enabled = false)
+ @Test(enabled = true)
public void test020FormatUserModification() throws Exception {
// GIVEN
ObjectDelta delta = parseDelta(USER_JACK_MODIFICATION_FILE);
+ PrismObject jack = PrismTestUtil.parseObject(new File(USER_JACK_FILE));
System.out.println(delta.debugDump());
// WHEN
- String deltaFormattedHideNone = textFormatter.formatObjectModificationDelta(delta, null, true);
+ String deltaFormattedHideNone = textFormatter.formatObjectModificationDelta(delta, null, true, jack, null);
System.out.println("no hidden paths + show operational attributes: " + deltaFormattedHideNone);
- String deltaFormattedHideOper = textFormatter.formatObjectModificationDelta(delta, null, false);
+ String deltaFormattedHideOper = textFormatter.formatObjectModificationDelta(delta, null, false, jack, null);
System.out.println("no hidden paths + hide operational attributes: " + deltaFormattedHideOper);
- String deltaFormattedHideAux = textFormatter.formatObjectModificationDelta(delta, auxiliaryPaths, true);
+ String deltaFormattedHideAux = textFormatter.formatObjectModificationDelta(delta, auxiliaryPaths, true, jack, null);
System.out.println("hide auxiliary paths + show operational attributes: " + deltaFormattedHideAux);
- String deltaFormattedHideAuxAndOper = textFormatter.formatObjectModificationDelta(delta, auxiliaryPaths, false);
+ String deltaFormattedHideAuxAndOper = textFormatter.formatObjectModificationDelta(delta, auxiliaryPaths, false, jack, null);
System.out.println("hide auxiliary paths + hide operational attributes: " + deltaFormattedHideAuxAndOper);
// THEN
- AssertJUnit.assertTrue("hidden operational attribute when it should be shown ('hide none')", deltaFormattedHideNone.contains("createTimestamp:"));
- AssertJUnit.assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide none')", deltaFormattedHideNone.contains("SPARROW"));
- AssertJUnit.assertTrue("hidden password change when it should be shown ('hide none')", deltaFormattedHideNone.contains("(protected string)"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide none')", deltaFormattedHideNone.contains("BLACK PEARL"));
+ checkNotes(deltaFormattedHideAux);
+ checkNotes(deltaFormattedHideAuxAndOper);
+ checkNotes(deltaFormattedHideNone);
+ checkNotes(deltaFormattedHideOper);
- AssertJUnit.assertTrue("shown operational attribute when it should be hidden ('hide oper')", !deltaFormattedHideOper.contains("createTimestamp:"));
- AssertJUnit.assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide oper')", deltaFormattedHideOper.contains("SPARROW"));
- AssertJUnit.assertTrue("hidden password change when it should be shown ('hide oper')", deltaFormattedHideOper.contains("(protected string)"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide oper')", deltaFormattedHideOper.contains("BLACK PEARL"));
+ assertTrue("hidden operational attribute when it should be shown ('hide none')", deltaFormattedHideNone.contains("createTimestamp:"));
+ assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide none')", deltaFormattedHideNone.contains("SPARROW"));
+ assertTrue("hidden password change when it should be shown ('hide none')", deltaFormattedHideNone.contains("(protected string)"));
+ assertTrue("hidden standard attribute when it should be shown ('hide none')", deltaFormattedHideNone.contains("BLACK PEARL"));
- AssertJUnit.assertTrue("shown auxiliary attribute (metadata) when it should be hidden ('hide aux')", !deltaFormattedHideAux.contains("createTimestamp:"));
- AssertJUnit.assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux')", !deltaFormattedHideAux.contains("SPARROW"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide aux')", deltaFormattedHideAux.contains("BLACK PEARL"));
+ assertTrue("shown operational attribute when it should be hidden ('hide oper')", !deltaFormattedHideOper.contains("createTimestamp:"));
+ assertTrue("hidden auxiliary attribute (family name) when it should be shown ('hide oper')", deltaFormattedHideOper.contains("SPARROW"));
+ assertTrue("hidden password change when it should be shown ('hide oper')", deltaFormattedHideOper.contains("(protected string)"));
+ assertTrue("hidden standard attribute when it should be shown ('hide oper')", deltaFormattedHideOper.contains("BLACK PEARL"));
- AssertJUnit.assertTrue("shown operational attribute when it should be hidden ('hide aux and oper')", !deltaFormattedHideAuxAndOper.contains("createTimestamp:"));
- AssertJUnit.assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux and oper')", !deltaFormattedHideAuxAndOper.contains("SPARROW"));
- AssertJUnit.assertTrue("hidden standard attribute when it should be shown ('hide aux and oper')", deltaFormattedHideAuxAndOper.contains("BLACK PEARL"));
+ assertTrue("shown auxiliary attribute (metadata) when it should be hidden ('hide aux')", !deltaFormattedHideAux.contains("createTimestamp:"));
+ assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux')", !deltaFormattedHideAux.contains("SPARROW"));
+ assertTrue("hidden standard attribute when it should be shown ('hide aux')", deltaFormattedHideAux.contains("BLACK PEARL"));
+
+ assertTrue("shown operational attribute when it should be hidden ('hide aux and oper')", !deltaFormattedHideAuxAndOper.contains("createTimestamp:"));
+ assertTrue("shown auxiliary attribute (family name) when it should be hidden ('hide aux and oper')", !deltaFormattedHideAuxAndOper.contains("SPARROW"));
+ assertTrue("hidden standard attribute when it should be shown ('hide aux and oper')", deltaFormattedHideAuxAndOper.contains("BLACK PEARL"));
+
+ }
+ private void checkNotes(String notification) {
+ String NOTES_DELIMITER = "Notes:";
+ int i = notification.indexOf(NOTES_DELIMITER);
+ if (i == -1) {
+ throw new AssertionError("No Notes section in " + notification);
+ }
+ String notes = notification.substring(i);
+ assertFalse(notes.contains("Assignment #1"));
+ assertFalse(notes.contains("Assignment #2"));
+ assertFalse(notes.contains("Assignment #3"));
+ assertTrue(notes.contains("Assignment[1]"));
+ assertTrue(notes.contains("Assignment[2]"));
+ assertFalse(notes.contains("Assignment[3]"));
}
@Test(enabled = true)
@@ -198,15 +222,15 @@ public void test030FormatAccount() throws Exception {
// THEN
- AssertJUnit.assertTrue("account name is not shown", jackFormattedHideNone.contains("name: jack"));
- AssertJUnit.assertTrue("account password is not shown", jackFormattedHideNone.contains("(protected string)"));
- AssertJUnit.assertTrue("administrative status is not shown", jackFormattedHideNone.contains("Administrative Status: ENABLED"));
- AssertJUnit.assertTrue("effective status is not shown", jackFormattedHideNone.contains("Effective Status: ENABLED"));
+ assertTrue("account name is not shown", jackFormattedHideNone.contains("name: jack"));
+ assertTrue("account password is not shown", jackFormattedHideNone.contains("(protected string)"));
+ assertTrue("administrative status is not shown", jackFormattedHideNone.contains("Administrative Status: ENABLED"));
+ assertTrue("effective status is not shown", jackFormattedHideNone.contains("Effective Status: ENABLED"));
- AssertJUnit.assertTrue("account name is not shown", jackFormattedHideAux.contains("name: jack"));
- AssertJUnit.assertTrue("account password is not shown", jackFormattedHideAux.contains("(protected string)"));
- AssertJUnit.assertTrue("administrative status is not shown", jackFormattedHideAux.contains("Administrative Status: ENABLED"));
- AssertJUnit.assertTrue("effective status is shown although it should be hidden", !jackFormattedHideAux.contains("Effective Status: ENABLED"));
+ assertTrue("account name is not shown", jackFormattedHideAux.contains("name: jack"));
+ assertTrue("account password is not shown", jackFormattedHideAux.contains("(protected string)"));
+ assertTrue("administrative status is not shown", jackFormattedHideAux.contains("Administrative Status: ENABLED"));
+ assertTrue("effective status is shown although it should be hidden", !jackFormattedHideAux.contains("Effective Status: ENABLED"));
// AssertJUnit.assertTrue("hidden operational attribute when it should be shown ('hide none')", jackFormattedHideNone.contains("createTimestamp:"));
// AssertJUnit.assertTrue("hidden auxiliary attribute (effective status) when it should be shown ('hide none')", jackFormattedHideNone.contains("Effective Status: ENABLED"));
diff --git a/model/notifications-impl/src/test/resources/changes/user-jack-modification.xml b/model/notifications-impl/src/test/resources/changes/user-jack-modification.xml
index fee366bdf63..46a9f80e5ee 100644
--- a/model/notifications-impl/src/test/resources/changes/user-jack-modification.xml
+++ b/model/notifications-impl/src/test/resources/changes/user-jack-modification.xml
@@ -20,7 +20,7 @@
xmlns:c='http://midpoint.evolveum.com/xml/ns/public/common/common-3'
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3">
c0c010c0-d34d-b33f-f00d-111111111111
-
+
replace
c:credentials/c:password
@@ -28,26 +28,31 @@
jack123456
-
-
+
+
replace
-
- SPARROW
-
-
-
+ familyName
+ SPARROW
+
+
replace
- c:metadata
-
- 2013-12-01T11:22:33.44
-
-
-
+ c:metadata/c:createTimestamp
+ 2013-12-01T11:22:33.44
+
+
+ replace
+ c:extension/piracy:ship
+ BLACK PEARL
+
+
+ replace
+ assignment[1]/activation/validTo
+ 2013-12-01T11:22:33.44
+
+
replace
- c:extension
-
- BLACK PEARL
-
-
+ assignment[2]/activation/validTo
+ 2014-10-03T11:22:33.44
+
diff --git a/model/notifications-impl/src/test/resources/objects/user-jack.xml b/model/notifications-impl/src/test/resources/objects/user-jack.xml
index a5c58fd46f1..2cd621cc402 100644
--- a/model/notifications-impl/src/test/resources/objects/user-jack.xml
+++ b/model/notifications-impl/src/test/resources/objects/user-jack.xml
@@ -56,4 +56,21 @@
enabled
enabled
+
+
+
+
+
+
+
+ 2013-12-01T11:22:33.44
+
+
+
+
+
+ 2015-01-01T00:00:00.00
+
+
+
From dbb0f1e12bb5a4bf4d37858b558e15956efbb6b2 Mon Sep 17 00:00:00 2001
From: Pavol Mederly
Date: Fri, 3 Oct 2014 11:19:22 +0200
Subject: [PATCH 12/19] Small fix.
---
.../impl/notifiers/SimpleFocalObjectNotifier.java | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java
index 9b2d3dd59de..930c0dde272 100644
--- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java
+++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleFocalObjectNotifier.java
@@ -131,6 +131,10 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S
fullName = ""; // TODO (currently it's not possible to get here)
}
+ if (fullName == null) {
+ fullName = ""; // "null" is not nice in notifications
+ }
+
ObjectDelta delta = ObjectDelta.summarize(((ModelEvent) event).getFocusDeltas());
StringBuilder body = new StringBuilder();
From f26ed43d28bf32e104d8148653a6b3ad55648c21 Mon Sep 17 00:00:00 2001
From: Erik Suta
Date: Fri, 3 Oct 2014 15:22:30 +0200
Subject: [PATCH 13/19] Resource Wizard update: - Fix for bug when
correlation filter expression was not saved - Added filterClause editor to
resource protected accounts editor - Better handling for validators - when
error occurs, error message is displazed immidiatel - fix for bug, when
deleting expression or filterClause would not be handled
---
.../input/ExpressionEditorPanel.java | 15 ++++++---------
.../input/ExpressionEditorPanel.properties | 1 +
.../component/input/SearchFilterPanel.java | 16 +++++++---------
.../input/dto/SearchFilterTypeDto.java | 8 +++++---
.../web/component/wizard/WizardStep.java | 11 ++++++-----
.../component/wizard/WizardStep.properties | 3 ++-
.../wizard/resource/SchemaHandlingStep.java | 12 ++++++------
.../ResourceProtectedEditor.html | 18 +-----------------
.../ResourceProtectedEditor.java | 19 ++++++-------------
.../ConditionalSearchFilterEditor.java | 17 ++++++++++++++++-
.../midpoint/web/util/ExpressionUtil.java | 3 ++-
11 files changed, 58 insertions(+), 65 deletions(-)
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.java
index e1ad66dcefd..a7057a34987 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.java
@@ -35,12 +35,10 @@
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.DropDownChoice;
-import org.apache.wicket.markup.html.form.EnumChoiceRenderer;
-import org.apache.wicket.markup.html.form.IChoiceRenderer;
-import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.markup.html.form.*;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
@@ -114,6 +112,7 @@ protected void onUpdate(AjaxRequestTarget target) {
});
type.setOutputMarkupId(true);
type.setOutputMarkupPlaceholderTag(true);
+ type.setNullValid(true);
add(type);
WebMarkupContainer languageContainer = new WebMarkupContainer(ID_LANGUAGE_CONTAINER);
@@ -193,10 +192,10 @@ protected void onUpdate(AjaxRequestTarget target) {
expression.setOutputMarkupId(true);
add(expression);
- AjaxLink update = new AjaxLink(ID_BUTTON_UPDATE) {
+ AjaxSubmitLink update = new AjaxSubmitLink(ID_BUTTON_UPDATE) {
@Override
- public void onClick(AjaxRequestTarget target) {
+ protected void onSubmit(AjaxRequestTarget target, Form> form) {
updateExpressionPerformed(target);
}
};
@@ -255,9 +254,7 @@ protected void updateExpressionPerformed(AjaxRequestTarget target){
/**
* Override this in component with ExpressionEditorPanel to provide additional functionality when expression is updated
* */
- public void performExpressionHook(AjaxRequestTarget target){
-
- }
+ public void performExpressionHook(AjaxRequestTarget target){}
/**
* Provide key for expression type label
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.properties b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.properties
index bb1b1076045..097edb658f7 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.properties
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/ExpressionEditorPanel.properties
@@ -24,6 +24,7 @@ ExpressionEditorPanel.message.cantSerialize=Could not create JAXBElement> from
ExpressionEditorPanel.message.expressionSuccess=Expression has been update successfully.
policyRef.nullValid=Choose One
+type.nullValid=Choose One
ExpressionEvaluatorType.LITERAL=Literal
ExpressionEvaluatorType.AS_IS=As is
ExpressionEvaluatorType.PATH=Path
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/SearchFilterPanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/SearchFilterPanel.java
index 01a3624068a..2779c34763f 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/SearchFilterPanel.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/SearchFilterPanel.java
@@ -16,7 +16,6 @@
package com.evolveum.midpoint.web.component.input;
-import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
@@ -25,7 +24,8 @@
import com.evolveum.midpoint.web.component.util.SimplePanel;
import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType;
import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;
@@ -41,7 +41,7 @@ public class SearchFilterPanel extends SimplePanel model;
+ protected IModel model;
public SearchFilterPanel(String id, IModel model){
super(id, model);
@@ -71,10 +71,10 @@ protected void initLayout(){
new PropertyModel(model, SearchFilterTypeDto.F_FILTER_CLAUSE));
add(filterClause);
- AjaxLink update = new AjaxLink(ID_BUTTON_UPDATE) {
+ AjaxSubmitLink update = new AjaxSubmitLink(ID_BUTTON_UPDATE) {
@Override
- public void onClick(AjaxRequestTarget target) {
+ protected void onSubmit(AjaxRequestTarget target, Form> form) {
updateClausePerformed(target);
}
};
@@ -86,7 +86,7 @@ private void updateClausePerformed(AjaxRequestTarget target){
model.getObject().updateFilterClause(getPageBase().getPrismContext());
success(getString("SearchFilterPanel.message.expressionSuccess"));
- } catch (SchemaException e){
+ } catch (Exception e){
LoggingUtils.logException(LOGGER, "Could not create MapXNode from provided XML filterClause.", e);
error(getString("SearchFilterPanel.message.cantSerialize"));
}
@@ -98,7 +98,5 @@ private void updateClausePerformed(AjaxRequestTarget target){
/**
* Override this in component with SearchFilterPanel to provide additional functionality when filterClause is updated
* */
- public void performFilterClauseHook(AjaxRequestTarget target){
- target.add();
- }
+ public void performFilterClauseHook(AjaxRequestTarget target){}
}
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/dto/SearchFilterTypeDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/dto/SearchFilterTypeDto.java
index cc78730dfb8..3a5e96c273d 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/dto/SearchFilterTypeDto.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/input/dto/SearchFilterTypeDto.java
@@ -17,9 +17,7 @@
package com.evolveum.midpoint.web.component.input.dto;
import com.evolveum.midpoint.prism.PrismContext;
-import com.evolveum.midpoint.prism.xnode.MapXNode;
import com.evolveum.midpoint.prism.xnode.RootXNode;
-import com.evolveum.midpoint.prism.xnode.XNode;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
@@ -27,7 +25,6 @@
import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType;
import org.apache.commons.lang.StringUtils;
-import javax.xml.namespace.QName;
import java.io.Serializable;
/**
@@ -86,6 +83,11 @@ public void updateFilterClause(PrismContext context) throws SchemaException{
RootXNode filterClauseNode = (RootXNode) context.parseToXNode(filterClause, PrismContext.LANG_XML);
filterObject.setFilterClauseXNode(filterClauseNode);
+ } else {
+ String oldDescription = filterObject.getDescription();
+
+ filterObject = new SearchFilterType();
+ filterObject.setDescription(oldDescription);
}
}
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.java
index 5225a583ce2..2ded7d323a2 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.java
@@ -26,6 +26,7 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.wizard.IWizard;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.AbstractReadOnlyModel;
@@ -49,15 +50,13 @@ public WizardStep() {
@Override
public Component getHeader(String id, Component parent, IWizard wizard) {
- Label header = new Label(id, new AbstractReadOnlyModel() {
+ return new Label(id, new AbstractReadOnlyModel() {
@Override
public String getObject() {
return getTitle();
}
});
-
- return header;
}
public PageBase getPageBase() {
@@ -127,8 +126,8 @@ protected IValidator createObjectClassValidator(final IModel
return new IValidator() {
@Override
- public void validate(IValidatable validatable) {
- String value = validatable.getValue();
+ public void validate(IValidatable validated) {
+ String value = validated.getValue();
List list = model.getObject();
List stringList = new ArrayList<>();
@@ -138,6 +137,8 @@ public void validate(IValidatable validatable) {
if(!stringList.contains(value)){
error(createStringResource("SchemaHandlingStep.message.validationError", value).getString());
+ AjaxRequestTarget target = getRequestCycle().find(AjaxRequestTarget.class);
+ target.add(getPageBase().getFeedbackPanel());
}
}
};
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.properties b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.properties
index 0eeda5ddcd6..54ab714af24 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.properties
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/WizardStep.properties
@@ -14,4 +14,5 @@
# limitations under the License.
#
-WizardStep.title=
\ No newline at end of file
+WizardStep.title=
+SchemaHandlingStep.message.validationError=Inserted objectClass value: '{0}' is not valid. Please provide valid objectClass value.
\ No newline at end of file
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaHandlingStep.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaHandlingStep.java
index 4f5f38a2bbd..f43b8e1fd48 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaHandlingStep.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/SchemaHandlingStep.java
@@ -537,7 +537,7 @@ private void dependencyEditPerformed(AjaxRequestTarget target){
new PropertyModel>(model, SchemaHandlingDto.F_SELECTED + ".dependency"));
getThirdRowContainer().replaceWith(newContainer);
- target.add(getThirdRowContainer());
+ target.add(getThirdRowContainer(), getPageBase().getFeedbackPanel());
}
private void iterationEditPerformed(AjaxRequestTarget target){
@@ -545,7 +545,7 @@ private void iterationEditPerformed(AjaxRequestTarget target){
new PropertyModel(model, SchemaHandlingDto.F_SELECTED + ".iteration"));
getThirdRowContainer().replaceWith(newContainer);
- target.add(getThirdRowContainer());
+ target.add(getThirdRowContainer(), getPageBase().getFeedbackPanel());
}
private void protectedEditPerformed(AjaxRequestTarget target){
@@ -553,7 +553,7 @@ private void protectedEditPerformed(AjaxRequestTarget target){
new PropertyModel>(model, SchemaHandlingDto.F_SELECTED + "._protected"));
getThirdRowContainer().replaceWith(newContainer);
- target.add(getThirdRowContainer());
+ target.add(getThirdRowContainer(), getPageBase().getFeedbackPanel());
}
private void activationEditPerformed(AjaxRequestTarget target){
@@ -561,7 +561,7 @@ private void activationEditPerformed(AjaxRequestTarget target){
new PropertyModel(model, SchemaHandlingDto.F_SELECTED + ".activation"));
getThirdRowContainer().replaceWith(newContainer);
- target.add(getThirdRowContainer());
+ target.add(getThirdRowContainer(), getPageBase().getFeedbackPanel());
}
private void credentialsEditPerformed(AjaxRequestTarget target){
@@ -569,7 +569,7 @@ private void credentialsEditPerformed(AjaxRequestTarget target){
new PropertyModel(model, SchemaHandlingDto.F_SELECTED + ".credentials"));
getThirdRowContainer().replaceWith(newContainer);
- target.add(getThirdRowContainer());
+ target.add(getThirdRowContainer(), getPageBase().getFeedbackPanel());
}
private void editAttributePerformed(AjaxRequestTarget target, ResourceAttributeDefinitionType object){
@@ -592,7 +592,7 @@ private void editAssociationPerformed(AjaxRequestTarget target, ResourceObjectAs
model.getObject().getSelected(), resourceModel.getObject());
getThirdRowContainer().replaceWith(newContainer);
- target.add(getThirdRowContainer());
+ target.add(getThirdRowContainer(), getPageBase().getFeedbackPanel());
} else {
warn(getString("SchemaHandlingStep.message.selectObjectClassAss"));
getThirdRowContainer().replaceWith(new WebMarkupContainer(ID_THIRD_ROW_CONTAINER));
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.html b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.html
index b7791df1e7a..4b88fba0afb 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.html
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.html
@@ -56,23 +56,7 @@
-
- -
-
-
- -
-
-
-
-
-
- -
-
-
- -
-
-
-
+
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.java
index 48d0edceca8..dbf66e346cf 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/schemahandling/ResourceProtectedEditor.java
@@ -16,15 +16,16 @@
package com.evolveum.midpoint.web.component.wizard.resource.component.schemahandling;
+import com.evolveum.midpoint.web.component.input.SearchFilterPanel;
import com.evolveum.midpoint.web.component.util.SimplePanel;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceObjectPatternType;
+import com.evolveum.prism.xml.ns._public.query_3.SearchFilterType;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
@@ -51,8 +52,7 @@ private static enum ChangeState{
private static final String ID_ACCOUNT_BODY = "accountBodyContainer";
private static final String ID_NAME = "name";
private static final String ID_UID = "uid";
- private static final String ID_FILTER_DESCRIPTION = "filterDescription";
- private static final String ID_FILTER_CLAUSE = "filterClause";
+ private static final String ID_FILTER_EDITOR = "filterClause";
private static final String ID_BUTTON_ADD = "addButton";
private static final String ID_BUTTON_DELETE = "deleteAccount";
@@ -150,16 +150,9 @@ public String getObject() {
uid.add(prepareAjaxOnComponentTagUpdateBehavior());
accountBody.add(uid);
- TextArea filterDescription = new TextArea<>(ID_FILTER_DESCRIPTION,
- new PropertyModel(item.getModelObject(), "filter.description"));
- filterDescription.add(prepareAjaxOnComponentTagUpdateBehavior());
- accountBody.add(filterDescription);
-
- //TODO - what is this? How should we edit this?
- TextField filterClause = new TextField<>(ID_FILTER_CLAUSE,
- new PropertyModel(item.getModelObject(), "filter.filterClauseXNode"));
- filterClause.add(prepareAjaxOnComponentTagUpdateBehavior());
- accountBody.add(filterClause);
+ SearchFilterPanel searchFilterPanel = new SearchFilterPanel<>(ID_FILTER_EDITOR,
+ new PropertyModel(item.getModelObject(), "filter"));
+ accountBody.add(searchFilterPanel);
}
};
repeater.setOutputMarkupId(true);
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/synchronization/ConditionalSearchFilterEditor.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/synchronization/ConditionalSearchFilterEditor.java
index 611937c3707..af39aadfc9f 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/synchronization/ConditionalSearchFilterEditor.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/wizard/resource/component/synchronization/ConditionalSearchFilterEditor.java
@@ -18,10 +18,12 @@
import com.evolveum.midpoint.web.component.input.ExpressionEditorPanel;
import com.evolveum.midpoint.web.component.input.SearchFilterPanel;
+import com.evolveum.midpoint.web.component.input.dto.SearchFilterTypeDto;
import com.evolveum.midpoint.web.component.util.LoadableModel;
import com.evolveum.midpoint.web.component.util.SimplePanel;
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.prism.xml.ns._public.query_3.SearchFilterType;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.model.IModel;
@@ -103,7 +105,20 @@ public String getExpressionLabelKey() {
};
add(expressionEditor);
- SearchFilterPanel filterClauseEditor = new SearchFilterPanel<>(ID_FILTER_CLAUSE_PANEL, getModel());
+ SearchFilterPanel filterClauseEditor = new SearchFilterPanel(ID_FILTER_CLAUSE_PANEL, getModel()){
+
+ @Override
+ public void performFilterClauseHook(AjaxRequestTarget target){
+ if(model != null && model.getObject() != null && ConditionalSearchFilterEditor.this.getModel() != null){
+ SearchFilterTypeDto dto = model.getObject();
+ SearchFilterType filter = dto.getFilterObject();
+
+ if(filter != null){
+ ConditionalSearchFilterEditor.this.getModelObject().setFilterClauseXNode(filter.getFilterClauseXNode());
+ }
+ }
+ }
+ };
add(filterClauseEditor);
}
}
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/ExpressionUtil.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/ExpressionUtil.java
index 1ac5073b47b..1be5b673bc8 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/ExpressionUtil.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/util/ExpressionUtil.java
@@ -80,6 +80,7 @@ public void setLanguage(String language) {
public static final String ELEMENT_PATH = "";
public static final String ELEMENT_VALUE = "";
public static final String ELEMENT_AS_IS = "";
+ public static final String ELEMENT_AS_IS_WITH_NS = "
Date: Fri, 3 Oct 2014 15:48:29 +0200
Subject: [PATCH 14/19] Fix for ChooseTypePanel - when assigning multiple
roles, the deletion of tenant attribute in one role cause next assignment to
crash.
---
.../configuration/component/ChooseTypePanel.java | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ChooseTypePanel.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ChooseTypePanel.java
index e7292f31311..e9d3fac588a 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ChooseTypePanel.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/page/admin/configuration/component/ChooseTypePanel.java
@@ -69,6 +69,7 @@ public String getObject(){
name.setOutputMarkupId(true);
AjaxLink choose = new AjaxLink(ID_LINK_CHOOSE) {
+
@Override
public void onClick(AjaxRequestTarget target) {
changeOptionPerformed(target);
@@ -76,6 +77,7 @@ public void onClick(AjaxRequestTarget target) {
};
AjaxLink remove = new AjaxLink(ID_LINK_REMOVE) {
+
@Override
public void onClick(AjaxRequestTarget target) {
setToDefault();
@@ -91,7 +93,7 @@ public void onClick(AjaxRequestTarget target) {
}
private void initDialog(){
- ModalWindow dialog = new ChooseTypeDialog(MODAL_ID_SHOW_CHOOSE_OPTIONS, getModel().getObject().getType()){
+ ModalWindow dialog = new ChooseTypeDialog(MODAL_ID_SHOW_CHOOSE_OPTIONS, getObjectTypeClass()){
@Override
protected void chooseOperationPerformed(AjaxRequestTarget target, ObjectType object){
@@ -151,7 +153,13 @@ private void changeOptionPerformed(AjaxRequestTarget target){
}
private void setToDefault(){
- getModel().setObject(new ObjectViewDto());
+ ObjectViewDto dto = new ObjectViewDto();
+ dto.setType(getObjectTypeClass());
+ getModel().setObject(dto);
+ }
+
+ private Class getObjectTypeClass(){
+ return getModel().getObject().getType();
}
public StringResourceModel createStringResource(String resourceKey, Object... objects) {
From 05abb27bf0b4020d2fb0efbe247be9a70137cf63 Mon Sep 17 00:00:00 2001
From: "Katarina Valalikova (katkav)"
Date: Sat, 4 Oct 2014 08:57:21 +0200
Subject: [PATCH 15/19] added possibility to override resource schema and set
secondary identifier - imporved consistency mechanism..
---
.../refinery/RefinedAttributeDefinition.java | 19 ++++++++++++++
.../RefinedObjectClassDefinition.java | 2 +-
.../xml/ns/public/common/common-3.xsd | 10 ++++++++
.../projector/ProjectionValuesProcessor.java | 10 --------
.../impl/ObjectAlreadyExistHandler.java | 25 +++++++++++++------
.../provisioning/util/ProvisioningUtil.java | 10 ++++++--
6 files changed, 55 insertions(+), 21 deletions(-)
diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java
index 5093fe73c1f..cd8c6bf3f27 100644
--- a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java
+++ b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java
@@ -48,6 +48,7 @@ public class RefinedAttributeDefinition extends ResourceAttributeDefinition impl
private String description;
private boolean tolerant = true;
private boolean isExclusiveStrong = false;
+ protected boolean secondaryIdentifier = false;
private List intolerantValuePattern;
private List tolerantValuePattern;
private ResourceAttributeDefinition attributeDefinition;
@@ -75,6 +76,14 @@ public void setTolerant(boolean tolerant) {
this.tolerant = tolerant;
}
+ public boolean isSecondaryIdentifier() {
+ return secondaryIdentifier;
+ }
+
+ public void setSecondaryIdentifier(boolean secondaryIdentifier) {
+ this.secondaryIdentifier = secondaryIdentifier;
+ }
+
@Override
public boolean canAdd() {
return canAdd(DEFAULT_LAYER);
@@ -328,6 +337,7 @@ static RefinedAttributeDefinition parse(ResourceAttributeDefinition schemaAttrDe
schemaLimitations.getAccess().setModify(schemaAttrDef.canModify());
schemaLimitations.getAccess().setRead(schemaAttrDef.canRead());
+
if (schemaHandlingAttrDefType != null) {
if (schemaHandlingAttrDefType.getDescription() != null) {
@@ -340,6 +350,12 @@ static RefinedAttributeDefinition parse(ResourceAttributeDefinition schemaAttrDe
rAttrDef.tolerant = schemaHandlingAttrDefType.isTolerant();
}
+ if (schemaHandlingAttrDefType.isSecondaryIdentifier() == null){
+ rAttrDef.secondaryIdentifier = false;
+ } else {
+ rAttrDef.secondaryIdentifier = schemaHandlingAttrDefType.isSecondaryIdentifier();
+ }
+
rAttrDef.tolerantValuePattern = schemaHandlingAttrDefType.getTolerantValuePattern();
rAttrDef.intolerantValuePattern = schemaHandlingAttrDefType.getIntolerantValuePattern();
@@ -365,6 +381,8 @@ static RefinedAttributeDefinition parse(ResourceAttributeDefinition schemaAttrDe
limitations.getAccess().setAdd(previousLimitations.getAccess().isAdd());
limitations.getAccess().setRead(previousLimitations.getAccess().isRead());
limitations.getAccess().setModify(previousLimitations.getAccess().isModify());
+ limitations.setSecondaryIdentifier(previousLimitations.isSecondaryIdentifier());
+ limitations.setUnique(previousLimitations.isUnique());
}
previousLimitations = limitations;
if (schemaHandlingAttrDefType != null) {
@@ -408,6 +426,7 @@ private static void applyLimitationsType(PropertyLimitations limitations, Proper
limitations.getAccess().setModify(accessType.isModify());
}
}
+
}
private static PropertyLimitationsType getLimitationsType(List limitationsTypes, LayerType layer) throws SchemaException {
diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinition.java b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinition.java
index 12517f5c97b..2211be3b61c 100644
--- a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinition.java
+++ b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedObjectClassDefinition.java
@@ -576,7 +576,7 @@ private void processIdentifiers(RefinedAttributeDefinition rAttrDef, ObjectClass
if (objectClassDef.isIdentifier(attrName)) {
((Collection)getIdentifiers()).add(rAttrDef);
}
- if (objectClassDef.isSecondaryIdentifier(attrName)) {
+ if (objectClassDef.isSecondaryIdentifier(attrName) || rAttrDef.isSecondaryIdentifier()) {
((Collection)getSecondaryIdentifiers()).add(rAttrDef);
}
}
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 1322670f293..96546f3d009 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
@@ -3567,6 +3567,16 @@
+
+
+
+ Indicated if the attribute should be considered as secondary identifier. If set to true,
+ this attribue is stored in repository and user for example by synchronization (correlation
+ rule), consistency mechanism, etc.
+
+
+
+
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java
index 2b37b481cb4..05ab5b29b73 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ProjectionValuesProcessor.java
@@ -389,16 +389,6 @@ private void processProjections(LensContext context,
}
LOGGER.trace("User {} satisfies correlation rules.", context.getFocusContext().getObjectNew());
-// result.computeStatus();
-// // if the result is fatal error, it may mean that the
-// // already exists expection occures before..but in this
-// // scenario it means, the exception was handled and we
-// // can mute the result to give better understanding of
-// // the situation which happend
-// if (result.isError()){
-// result.muteError();
-// }
-//
// Re-do this same iteration again (do not increase iteration count).
// It will recompute the values and therefore enforce the user deltas and enable reconciliation
skipUniquenessCheck = true; // to avoid endless loop
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
index 400e58b1e88..5416f1544f9 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
@@ -32,6 +32,7 @@
import com.evolveum.midpoint.prism.query.AndFilter;
import com.evolveum.midpoint.prism.query.EqualFilter;
import com.evolveum.midpoint.prism.query.ObjectQuery;
+import com.evolveum.midpoint.prism.query.OrFilter;
import com.evolveum.midpoint.prism.query.RefFilter;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.provisioning.api.ResourceObjectShadowChangeDescription;
@@ -124,21 +125,29 @@ public T handleError(T shadow, FailedOperation op, Except
private ObjectQuery createQueryByIcfName(ShadowType shadow) throws SchemaException {
// TODO: error handling TODO TODO TODO set matching rule instead of null in equlas filter
Collection> secondaryIdentifiers = ShadowUtil.getSecondaryIdentifiers(shadow);
- PrismProperty nameProperty = null;
- if (secondaryIdentifiers.size() != 1){
- nameProperty = shadow.getAttributes().asPrismContainerValue()
- .findProperty(new QName(SchemaConstants.NS_ICF_SCHEMA, "name"));
- } else {
- nameProperty = secondaryIdentifiers.iterator().next();
+
+ List secondaryIdentifierFilters = new ArrayList();
+
+ for (ResourceAttribute> secondaryIdentifier : secondaryIdentifiers){
+ EqualFilter equal = EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, secondaryIdentifier.getElementName()), secondaryIdentifier);
+ secondaryIdentifierFilters.add(equal);
}
+ OrFilter orSecondary = OrFilter.createOr((List)secondaryIdentifierFilters);
+// PrismProperty nameProperty = null;
+// if (secondaryIdentifiers.size() != 1){
+// nameProperty = shadow.getAttributes().asPrismContainerValue()
+// .findProperty(new QName(SchemaConstants.NS_ICF_SCHEMA, "name"));
+// } else {
+// nameProperty = secondaryIdentifiers.iterator().next();
+// }
- EqualFilter nameFilter = EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, nameProperty.getDefinition().getName()),nameProperty);
+// EqualFilter nameFilter = EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, nameProperty.getDefinition().getName()),nameProperty);
RefFilter resourceRefFilter = RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class,
prismContext, shadow.getResourceRef().getOid());
EqualFilter objectClassFilter = EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext,
null, shadow.getObjectClass());
- ObjectQuery query = ObjectQuery.createObjectQuery(AndFilter.createAnd(nameFilter, resourceRefFilter,
+ ObjectQuery query = ObjectQuery.createObjectQuery(AndFilter.createAnd(orSecondary, resourceRefFilter,
objectClassFilter));
return query;
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java
index ac1f0a995b5..36937c78166 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java
@@ -197,7 +197,10 @@ public static String getResourceOidFromFilter(List extends ObjectFilter> condi
return values.get(0).getOid();
}
if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())){
- return getResourceOidFromFilter(((NaryLogicalFilter) f).getConditions());
+ String resourceOid = getResourceOidFromFilter(((NaryLogicalFilter) f).getConditions());
+ if (resourceOid != null){
+ return resourceOid;
+ }
}
}
@@ -221,7 +224,10 @@ public static T getValueFromFilter(List extends ObjectFilter> conditions,
return (T) ((PrismPropertyValue)values.get(0)).getValue();
}
if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())){
- return getValueFromFilter(((NaryLogicalFilter) f).getConditions(), propertyName);
+ T value = getValueFromFilter(((NaryLogicalFilter) f).getConditions(), propertyName);
+ if (value != null){
+ return value;
+ }
}
}
From 51e280e68bbfa3bb693042c9dfe69502b10ec0f9 Mon Sep 17 00:00:00 2001
From: "Katarina Valalikova (katkav)"
Date: Sat, 4 Oct 2014 10:22:43 +0200
Subject: [PATCH 16/19] fixing build..sorry.
---
.../midpoint/common/refinery/RefinedAttributeDefinition.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java
index cd8c6bf3f27..2b0c882d82d 100644
--- a/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java
+++ b/infra/common/src/main/java/com/evolveum/midpoint/common/refinery/RefinedAttributeDefinition.java
@@ -381,8 +381,6 @@ static RefinedAttributeDefinition parse(ResourceAttributeDefinition schemaAttrDe
limitations.getAccess().setAdd(previousLimitations.getAccess().isAdd());
limitations.getAccess().setRead(previousLimitations.getAccess().isRead());
limitations.getAccess().setModify(previousLimitations.getAccess().isModify());
- limitations.setSecondaryIdentifier(previousLimitations.isSecondaryIdentifier());
- limitations.setUnique(previousLimitations.isUnique());
}
previousLimitations = limitations;
if (schemaHandlingAttrDefType != null) {
From fd5b9f9ea5faabccdcbaf52a5ceab8103b863895 Mon Sep 17 00:00:00 2001
From: "Katarina Valalikova (katkav)"
Date: Sun, 5 Oct 2014 20:07:19 +0200
Subject: [PATCH 17/19] new model execute option - limitPropagation * improved
compensation mechanism for already exits situation - propagate changes
related only to the conflicting shadow * configurable changes propagation -
can be propagated only to the source resource * skipping some steps while
computing changes - if specified to propagate changes only for source
resource
---
.../xml/ns/public/common/common-3.xsd | 21 ++
.../model/api/ModelExecuteOptions.java | 33 ++-
.../model/impl/lens/ChangeExecutor.java | 10 +-
.../midpoint/model/impl/lens/LensContext.java | 17 ++
.../impl/lens/LensProjectionContext.java | 13 ++
.../lens/projector/AssignmentProcessor.java | 99 ++++++---
.../impl/lens/projector/ContextLoader.java | 25 +++
.../lens/projector/DependencyProcessor.java | 12 +-
.../impl/lens/projector/InboundProcessor.java | 4 +
.../projector/ObjectTemplateProcessor.java | 41 +---
.../impl/sync/SynchronizationService.java | 50 ++++-
.../impl/ObjectAlreadyExistHandler.java | 11 +-
.../provisioning/util/ProvisioningUtil.java | 190 ++++++++++--------
13 files changed, 345 insertions(+), 181 deletions(-)
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 96546f3d009..ebba96fe8f1 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
@@ -5204,6 +5204,19 @@
No additional read will be executed.
+
+
+
+
+ If set to true, applicable synchronization reactions will propagate changes only form/to source
+ resource. In the case focus cotains links to another resource this will be not recomputed
+ and after reaction execution there may be small inconsistencies.
+
+ It can improve performance for example for initial import.
+
+ Default value is false.
+
+
@@ -5324,6 +5337,7 @@
+
@@ -8550,6 +8564,13 @@
+
+
+
+ Option to limit change computation and execution only for the source resource.
+
+
+
diff --git a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java
index e05fbc8d2f4..a01d334b7cb 100644
--- a/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java
+++ b/model/model-api/src/main/java/com/evolveum/midpoint/model/api/ModelExecuteOptions.java
@@ -65,6 +65,11 @@ public class ModelExecuteOptions implements Serializable, Cloneable {
Boolean isImport;
+ /**
+ * Option to limit propagation only for the source resource
+ */
+ Boolean limitPropagation;
+
public Boolean getForce() {
return force;
@@ -224,6 +229,27 @@ public static boolean isExecuteImmediatelyAfterApproval(ModelExecuteOptions opti
}
return options.executeImmediatelyAfterApproval;
}
+
+ public static ModelExecuteOptions createIsLimitPropagation() {
+ ModelExecuteOptions opts = new ModelExecuteOptions();
+ opts.setLimitPropagation(true);
+ return opts;
+
+ }
+
+ public void setLimitPropagation(Boolean limitPropagation) {
+ this.limitPropagation = limitPropagation;
+ }
+
+ public static boolean isLimitPropagation(ModelExecuteOptions options){
+ if (options == null){
+ return false;
+ }
+ if (options.limitPropagation == null){
+ return false;
+ }
+ return options.limitPropagation;
+ }
public static ModelExecuteOptions createExecuteImmediatelyAfterApproval(){
ModelExecuteOptions opts = new ModelExecuteOptions();
@@ -240,6 +266,7 @@ public ModelExecuteOptionsType toModelExecutionOptionsType() {
retval.setExecuteImmediatelyAfterApproval(executeImmediatelyAfterApproval);
retval.setOverwrite(overwrite);
retval.setIsImport(isImport);
+ retval.setLimitPropagation(limitPropagation);
return retval;
}
@@ -255,6 +282,7 @@ public static ModelExecuteOptions fromModelExecutionOptionsType(ModelExecuteOpti
retval.setExecuteImmediatelyAfterApproval(type.isExecuteImmediatelyAfterApproval());
retval.setOverwrite(type.isOverwrite());
retval.setIsImport(type.isIsImport());
+ retval.setLimitPropagation(type.isLimitPropagation());
return retval;
}
@@ -286,6 +314,9 @@ public static ModelExecuteOptions fromRestOptions(List options){
if (ModelExecuteOptionsType.F_IS_IMPORT.getLocalPart().equals(option)){
retVal.setIsImport(true);;
}
+ if (ModelExecuteOptionsType.F_LIMIT_PROPAGATION.getLocalPart().equals(option)){
+ retVal.setIsImport(true);;
+ }
}
return retVal;
@@ -297,7 +328,7 @@ public String toString(){
+ ",reconcile=" + reconcile
+ ",executeImmediatelyAfterApproval="
+ executeImmediatelyAfterApproval + ",overwrite=" + overwrite
- + "]";
+ + "limitPropagation="+limitPropagation+"]";
}
public ModelExecuteOptions clone() {
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java
index eb1f8a73688..f4fe52cf74d 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/ChangeExecutor.java
@@ -169,7 +169,7 @@ public void executeChanges(LensContext syncContext, Ta
throw e;
} catch (ObjectAlreadyExistsException e) {
subResult.computeStatus();
- if (!subResult.isSuccess()) {
+ if (!subResult.isSuccess() && !subResult.isHandledError()) {
subResult.recordFatalError(e);
}
result.computeStatusComposite();
@@ -205,6 +205,11 @@ public void executeChanges(LensContext syncContext, Ta
if (accCtx.getWave() != syncContext.getExecutionWave()) {
continue;
}
+
+ if (!accCtx.isCanProject()){
+ continue;
+ }
+
OperationResult subResult = result.createSubresult(OPERATION_EXECUTE_PROJECTION+"."+accCtx.getObjectTypeClass().getSimpleName());
subResult.addContext("discriminator", accCtx.getResourceShadowDiscriminator());
if (accCtx.getResource() != null) {
@@ -290,7 +295,8 @@ public void executeChanges(LensContext syncContext, Ta
// and also do not set fatal error to the operation result, this is a special case
// if it is fatal, it will be set later
// but we need to set some result
- subResult.recordHandledError(e);
+ subResult.recordSuccess();
+ subResult.muteLastSubresultError();
continue;
} catch (CommunicationException e) {
recordProjectionExecutionException(e, accCtx, subResult, SynchronizationPolicyDecision.BROKEN);
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java
index 4380b5407e8..3eb5567f066 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java
@@ -98,6 +98,8 @@ public class LensContext implements ModelContext {
* Current wave of execution.
*/
int executionWave = 0;
+
+ private String triggeredResourceOid;
transient private boolean isFresh = false;
transient private boolean isRequestAuthorized = false;
@@ -149,6 +151,21 @@ protected PrismContext getNotNullPrismContext() {
public ProvisioningService getProvisioningService() {
return provisioningService;
}
+
+ public void setTriggeredResource(String triggeredResourceOid) {
+ this.triggeredResourceOid = triggeredResourceOid;
+ }
+
+ public void setTriggeredResource(ResourceType triggeredResource) {
+ if (triggeredResource != null){
+ this.triggeredResourceOid = triggeredResource.getOid();
+ }
+ }
+
+ public String getTriggeredResourceOid() {
+ return triggeredResourceOid;
+ }
+
@Override
public ModelState getState() {
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java
index 29c09f08093..c7f53d5dd3c 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensProjectionContext.java
@@ -132,6 +132,11 @@ public class LensProjectionContext extends LensElementContext implem
*/
private boolean doReconciliation;
+ /**
+ * false if the context should be not taken into the account while synchronizing changes from other resource
+ */
+ private boolean canProject = true;
+
/**
@@ -510,6 +515,14 @@ public ValuePolicyType getAccountPasswordPolicy() {
return accountPasswordPolicy;
}
+ public void setCanProject(boolean canProject) {
+ this.canProject = canProject;
+ }
+
+ public boolean isCanProject() {
+ return canProject;
+ }
+
public void setAccountPasswordPolicy(ValuePolicyType accountPasswordPolicy) {
this.accountPasswordPolicy = accountPasswordPolicy;
}
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java
index c8c29906a8a..af08e1ad72f 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/AssignmentProcessor.java
@@ -16,7 +16,19 @@
package com.evolveum.midpoint.model.impl.lens.projector;
-import ch.qos.logback.classic.Logger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
import com.evolveum.midpoint.common.ActivationComputer;
import com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator;
@@ -39,7 +51,15 @@
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.model.impl.lens.LensUtil;
-import com.evolveum.midpoint.prism.*;
+import com.evolveum.midpoint.prism.PrismContainer;
+import com.evolveum.midpoint.prism.PrismContainerDefinition;
+import com.evolveum.midpoint.prism.PrismContainerValue;
+import com.evolveum.midpoint.prism.PrismContext;
+import com.evolveum.midpoint.prism.PrismObjectDefinition;
+import com.evolveum.midpoint.prism.PrismPropertyValue;
+import com.evolveum.midpoint.prism.PrismReferenceDefinition;
+import com.evolveum.midpoint.prism.PrismReferenceValue;
+import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.delta.ContainerDelta;
import com.evolveum.midpoint.prism.delta.DeltaMapTriple;
import com.evolveum.midpoint.prism.delta.DeltaSetTriple;
@@ -47,20 +67,18 @@
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.PlusMinusZero;
import com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple;
-import com.evolveum.midpoint.prism.delta.PropertyDelta;
import com.evolveum.midpoint.prism.path.IdItemPathSegment;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.path.NameItemPathSegment;
import com.evolveum.midpoint.provisioning.api.ProvisioningService;
import com.evolveum.midpoint.repo.api.RepositoryService;
+import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
-import com.evolveum.midpoint.schema.util.MiscSchemaUtil;
+import com.evolveum.midpoint.schema.util.ObjectResolver;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.SchemaDebugUtil;
-import com.evolveum.midpoint.schema.util.ObjectResolver;
import com.evolveum.midpoint.task.api.Task;
-import com.evolveum.midpoint.util.DebugUtil;
-import com.evolveum.midpoint.util.MiscUtil;
+import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
@@ -68,7 +86,6 @@
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.exception.SystemException;
-import com.evolveum.midpoint.util.exception.TunnelException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractRoleType;
@@ -77,28 +94,11 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConstructionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ExclusionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectTemplateType;
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.ProjectionPolicyType;
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.ShadowKindType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Component;
-
-import javax.xml.datatype.DatatypeConstants;
-import javax.xml.datatype.XMLGregorianCalendar;
-import javax.xml.namespace.QName;
-
-import java.util.*;
-import java.util.Map.Entry;
/**
* Assignment processor is recomputing user assignments. It recomputes all the assignements whether they are direct
@@ -157,6 +157,10 @@ public void processAssignmentsProjections(LensContext
// We can do this only for FocusType.
return;
}
+// if (ModelExecuteOptions.isLimitPropagation(context.getOptions()) && SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(QNameUtil.uriToQName(context.getChannel()))){
+// //do not execute assignment if the execution was triggered by compensation mechanism and limitPropagation is set
+// return;
+// }
processAssignmentsProjectionsWithFocus((LensContext extends FocusType>)context, now, task, result);
}
@@ -463,6 +467,8 @@ private void processAssignmentsProjectionsWithFocus(LensCo
LOGGER.trace("Projection maps:\n{}", constructionMapTriple.debugDump());
}
+
+
// Now we are processing constructions from all the three sets once again. We will create projection contexts
// for them if not yet created. Now we will do the usual routing for converting the delta triples to deltas.
// I.e. zero means unchanged, plus means added, minus means deleted. That will be recorded in the SynchronizationPolicyDecision.
@@ -470,13 +476,30 @@ private void processAssignmentsProjectionsWithFocus(LensCo
// actual attribute deltas (in consolidation processor).
Collection allAccountTypes = constructionMapTriple.unionKeySets();
for (ResourceShadowDiscriminator rat : allAccountTypes) {
-
+
if (rat.getResourceOid() == null) {
throw new IllegalStateException("Resource OID null in ResourceAccountType during assignment processing");
}
if (rat.getIntent() == null) {
throw new IllegalStateException("Account type is null in ResourceAccountType during assignment processing");
}
+
+ boolean processOnlyExistingProjCxts = false;
+ if (ModelExecuteOptions.isLimitPropagation(context.getOptions())){
+ if (context.getTriggeredResourceOid() != null
+ && !rat.getResourceOid().equals(context.getTriggeredResourceOid())) {
+ LOGGER.trace(
+ "Skipping processing construction for shadow identified by {} because of limitation to propagate changes only for resource {}",
+ rat, context.getTriggeredResourceOid());
+ continue;
+ }
+
+ if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(QNameUtil.uriToQName(context.getChannel()))){
+ LOGGER.trace("Processing of shadow identified by {} will be skipped because of limitation for discovery channel.");
+ processOnlyExistingProjCxts = true;
+ }
+ }
+
String desc = rat.toHumanReadableString();
// SITUATION: The projection should exist (if valid), there is NO CHANGE in assignments
@@ -484,6 +507,9 @@ private void processAssignmentsProjectionsWithFocus(LensCo
LensProjectionContext projectionContext = context.findProjectionContext(rat);
if (projectionContext == null) {
+ if (processOnlyExistingProjCxts){
+ continue;
+ }
// The projection should exist before the change but it does not
// This happens during reconciliation if there is an inconsistency.
// Pretend that the assignment was just added. That should do.
@@ -516,6 +542,9 @@ private void processAssignmentsProjectionsWithFocus(LensCo
LensProjectionContext projectionContext = context.findProjectionContext(rat);
if (projectionContext == null) {
+ if (processOnlyExistingProjCxts){
+ continue;
+ }
// The projection should exist before the change but it does not
// This happens during reconciliation if there is an inconsistency.
// Pretend that the assignment was just added. That should do.
@@ -532,8 +561,14 @@ private void processAssignmentsProjectionsWithFocus(LensCo
} else if (plusPack.hasValidAssignment() && !minusPack.hasValidAssignment()) {
// Assignment became valid. Same as if it was assigned.
- LensProjectionContext projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
- projectionContext.setAssigned(true);
+ LensProjectionContext projectionContext = context.findProjectionContext(rat);
+ if (projectionContext == null){
+ if (processOnlyExistingProjCxts){
+ continue;
+ }
+ projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
+ }
+ projectionContext.setAssigned(true);
projectionContext.setLegalOld(false);
AssignmentPolicyEnforcementType assignmentPolicyEnforcement = projectionContext.getAssignmentPolicyEnforcementType();
if (assignmentPolicyEnforcement != AssignmentPolicyEnforcementType.NONE) {
@@ -544,7 +579,13 @@ private void processAssignmentsProjectionsWithFocus(LensCo
} else if (!plusPack.hasValidAssignment() && minusPack.hasValidAssignment()) {
// Assignment became invalid. Same as if it was unassigned.
if (accountExists(context,rat)) {
- LensProjectionContext projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
+ LensProjectionContext projectionContext = context.findProjectionContext(rat);
+ if (projectionContext == null){
+ if (processOnlyExistingProjCxts){
+ continue;
+ }
+ projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
+ }
projectionContext.setAssigned(false);
projectionContext.setLegalOld(true);
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java
index 1ffff27a164..08f2d919636 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ContextLoader.java
@@ -24,6 +24,7 @@
import javax.xml.namespace.QName;
import com.evolveum.midpoint.schema.constants.ObjectTypes;
+import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
@@ -34,6 +35,7 @@
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator;
+import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.context.SynchronizationPolicyDecision;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
@@ -56,6 +58,7 @@
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ShadowUtil;
+import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
@@ -481,6 +484,11 @@ private void loadLinkRefsFromFocus(LensContext context,
throw new SchemaException("Null or empty OID in link reference in " + focus);
}
LensProjectionContext existingAccountContext = findAccountContext(oid, context);
+
+ if (!canBeLoaded(context, existingAccountContext)){
+ continue;
+ }
+
if (existingAccountContext != null) {
// TODO: do we need to reload the account inside here? yes we need
@@ -769,6 +777,15 @@ private void loadProjectionContextsSync(LensContext co
}
}
+ private boolean canBeLoaded(LensContext context, LensProjectionContext projCtx){
+ if (QNameUtil.qNameToUri(SchemaConstants.CHANGE_CHANNEL_DISCOVERY).equals(context.getChannel()) && projCtx == null && ModelExecuteOptions.isLimitPropagation(context.getOptions())) {
+ // avoid to create projection context if the channel which
+ // triggered this operation is discovery..we need only
+ // projection context of discovered shadow
+ return false;
+ }
+ return true;
+ }
private LensProjectionContext getOrCreateAccountContext(LensContext context,
PrismObject account, OperationResult result) throws ObjectNotFoundException,
CommunicationException, SchemaException, ConfigurationException, SecurityViolationException {
@@ -961,6 +978,14 @@ private void finishLoadOfProjectionContext(LensContext
}
}
+ //set limitation, e.g. if this projection context should be recomputed and processed by projector
+ if (ModelExecuteOptions.isLimitPropagation(context.getOptions())){
+ if (context.getTriggeredResourceOid() != null){
+ if (!context.getTriggeredResourceOid().equals(resourceOid)){
+ projContext.setCanProject(false);
+ }
+ }
+ }
}
private boolean needToReload(LensContext context,
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
index 87d98aeda4e..5efcdb08c55 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/DependencyProcessor.java
@@ -448,6 +448,9 @@ public void preprocessDependencies(LensContext context
}
for (LensProjectionContext projContext : context.getProjectionContexts()){
+ if (!projContext.isCanProject()){
+ continue;
+ }
for (ResourceObjectTypeDependencyType dependency: projContext.getDependencies()) {
ResourceShadowDiscriminator refRat = new ResourceShadowDiscriminator(dependency,
@@ -456,20 +459,17 @@ public void preprocessDependencies(LensContext context
LensProjectionContext dependencyAccountContext = context.findProjectionContext(refRat);
ResourceObjectTypeDependencyStrictnessType strictness = ResourceTypeUtil.getDependencyStrictness(dependency);
if (dependencyAccountContext != null){
+ if (!dependencyAccountContext.isCanProject()){
+ continue;
+ }
// We have the context of the object that we depend on. We need to check if it was provisioned.
if (strictness == ResourceObjectTypeDependencyStrictnessType.STRICT
|| strictness == ResourceObjectTypeDependencyStrictnessType.RELAXED) {
if (wasExecuted(dependencyAccountContext)) {
// everything OK
if (ResourceTypeUtil.isForceLoadDependentShadow(dependency) && !dependencyAccountContext.isDelete()){
- LOGGER.info("FORCE TO LOAD FULL ACCOUNT " + dependencyAccountContext);
dependencyAccountContext.setDoReconciliation(true);
projContext.setDoReconciliation(true);
-// if (dependencyAccountContext.getExecutedDeltas() != null && !dependencyAccountContext.getExecutedDeltas().isEmpty()){
-// if (context.getProjectionWave() < context.getExecutionWave()){
-// context.resetProjectionWave();
-// }
-// }
}
}
}
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java
index 8180ce826c6..de830d931f3 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/InboundProcessor.java
@@ -135,6 +135,10 @@ void processInboundFocal(LensContext context, Task task
try {
for (LensProjectionContext accountContext : context.getProjectionContexts()) {
+ if (!accountContext.isCanProject()){
+ LOGGER.trace("Skipping processing of inbound expressions for account {}: there is a limit to propagate changes only from resource", context.getTriggeredResourceOid());
+ continue;
+ }
ResourceShadowDiscriminator rat = accountContext.getResourceShadowDiscriminator();
ObjectDelta aPrioriDelta = getAPrioriDelta(context, accountContext);
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ObjectTemplateProcessor.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ObjectTemplateProcessor.java
index 8dc00a7fe5e..7d82d1629e4 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ObjectTemplateProcessor.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/projector/ObjectTemplateProcessor.java
@@ -15,94 +15,58 @@
*/
package com.evolveum.midpoint.model.impl.lens.projector;
-import static com.evolveum.midpoint.common.InternalsConfig.consistencyChecks;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import javax.xml.bind.JAXBElement;
import javax.xml.datatype.DatatypeConstants;
import javax.xml.datatype.XMLGregorianCalendar;
-import javax.xml.namespace.QName;
-import org.apache.xpath.FoundIndex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import com.evolveum.midpoint.common.ActivationComputer;
-import com.evolveum.midpoint.common.Clock;
-import com.evolveum.midpoint.common.refinery.RefinedAttributeDefinition;
-import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
+import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.PolicyViolationException;
import com.evolveum.midpoint.model.common.expression.ExpressionFactory;
-import com.evolveum.midpoint.model.common.expression.ExpressionVariables;
import com.evolveum.midpoint.model.common.expression.ObjectDeltaObject;
-import com.evolveum.midpoint.model.common.expression.StringPolicyResolver;
import com.evolveum.midpoint.model.common.mapping.Mapping;
import com.evolveum.midpoint.model.common.mapping.MappingFactory;
import com.evolveum.midpoint.model.impl.ModelObjectResolver;
import com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
-import com.evolveum.midpoint.model.impl.lens.LensProjectionContext;
import com.evolveum.midpoint.model.impl.lens.LensUtil;
import com.evolveum.midpoint.model.impl.trigger.RecomputeTriggerHandler;
-import com.evolveum.midpoint.model.impl.util.Utils;
-import com.evolveum.midpoint.prism.ComplexTypeDefinition;
-import com.evolveum.midpoint.prism.Item;
-import com.evolveum.midpoint.prism.ItemDefinition;
-import com.evolveum.midpoint.prism.OriginType;
import com.evolveum.midpoint.prism.PrismContainerDefinition;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
-import com.evolveum.midpoint.prism.PrismPropertyDefinition;
-import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.PrismValue;
-import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.ContainerDelta;
import com.evolveum.midpoint.prism.delta.DeltaSetTriple;
import com.evolveum.midpoint.prism.delta.ItemDelta;
-import com.evolveum.midpoint.prism.delta.ObjectDelta;
-import com.evolveum.midpoint.prism.delta.PropertyDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.repo.api.RepositoryService;
-import com.evolveum.midpoint.schema.constants.ExpressionConstants;
-import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
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.xml.ns._public.common.common_3.ActivationStatusType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.GenerateExpressionEvaluatorType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingStrengthType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.MappingType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectTemplateMappingEvaluationPhaseType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectTemplateMappingType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectTemplateType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.StringPolicyType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.TimeIntervalStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
-import com.evolveum.midpoint.xml.ns._public.common.common_3.ValuePolicyType;
-import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
/**
* Processor to handle object template.
@@ -148,7 +112,8 @@ public void processTemplate(LensContext context, Object
LOGGER.trace("Skipping processing of object template: focus delete");
return;
}
- ObjectTemplateType objectTemplate = context.getFocusTemplate();
+
+ ObjectTemplateType objectTemplate = context.getFocusTemplate();
if (objectTemplate == null) {
// No applicable template
LOGGER.trace("Skipping processing of object template: no object template");
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java
index 0023ab134ec..62424934432 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java
@@ -39,6 +39,7 @@
import com.evolveum.midpoint.audit.api.AuditService;
import com.evolveum.midpoint.common.InternalsConfig;
import com.evolveum.midpoint.common.refinery.ResourceShadowDiscriminator;
+import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.PolicyViolationException;
import com.evolveum.midpoint.model.common.expression.Expression;
import com.evolveum.midpoint.model.common.expression.ExpressionEvaluationContext;
@@ -89,6 +90,7 @@
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.MiscUtil;
+import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
@@ -652,11 +654,16 @@ private void reactToChange(Class focusClass, ResourceOb
}
}
+ Boolean limitPropagation = determinePropagationLimitation(synchronizationPolicy, reactionDefinition, change.getSourceChannel());
+ ModelExecuteOptions options = new ModelExecuteOptions();
+ options.setReconcile(doReconciliation);
+ options.setLimitPropagation(limitPropagation);
+
boolean willSynchronize = isSynchronize(reactionDefinition);
LensContext lensContext = null;
if (willSynchronize) {
lensContext = createLensContext(focusClass, change, reactionDefinition, synchronizationPolicy, situation,
- doReconciliation, configuration, parentResult);
+ options, configuration, parentResult);
}
if (LOGGER.isTraceEnabled() && lensContext != null) {
@@ -693,17 +700,46 @@ private Boolean determineReconciliation(ObjectSynchronizationType synchronizatio
}
return null;
}
+
+ private Boolean determinePropagationLimitation(ObjectSynchronizationType synchronizationPolicy,
+ SynchronizationReactionType reactionDefinition, String channel) {
+
+ if (StringUtils.isNotBlank(channel)){
+ QName channelQName = QNameUtil.uriToQName(channel);
+ // discovery channel is used when compensating some inconsistent
+ // state. Therefe we do not want to propagate changes to other
+ // resource. We only want to resolve the problem and continue in
+ // previous provisioning/synchronization during which his
+ // compensation was triggered
+ if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(channelQName)){
+ return true;
+ }
+ }
+
+ if (reactionDefinition.isLimitPropagation() != null) {
+ return reactionDefinition.isLimitPropagation();
+ }
+ if (synchronizationPolicy.isLimitPropagation() != null) {
+ return synchronizationPolicy.isLimitPropagation();
+ }
+ return null;
+ }
private LensContext createLensContext(Class focusClass, ResourceObjectShadowChangeDescription change,
SynchronizationReactionType reactionDefinition, ObjectSynchronizationType synchronizationPolicy,
- SynchronizationSituation situation, Boolean doReconciliation, PrismObject configuration,
+ SynchronizationSituation situation, ModelExecuteOptions options, PrismObject configuration,
OperationResult parentResult) throws ObjectNotFoundException, SchemaException {
LensContext context = contextFactory.createSyncContext(focusClass, change);
context.setLazyAuditRequest(true);
context.setSystemConfiguration(configuration);
-
- ResourceType resource = change.getResource().asObjectable();
+ context.setOptions(options);
+
+ ResourceType resource = change.getResource().asObjectable();
+ if (ModelExecuteOptions.isLimitPropagation(options)){
+ context.setTriggeredResource(resource);
+ }
+
context.rememberResource(resource);
PrismObject shadow = getShadowFromChange(change);
if (InternalsConfig.consistencyChecks) shadow.checkConsistence();
@@ -742,10 +778,8 @@ private LensContext createLensContext(Class focusCla
projectionContext.setExists(true);
}
- if (doReconciliation != null) {
- projectionContext.setDoReconciliation(doReconciliation);
- }
-
+ projectionContext.setDoReconciliation(ModelExecuteOptions.isReconcile(options));
+
// Focus context
if (situation.getCurrentOwner() != null) {
F focusType = situation.getCurrentOwner();
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
index 5416f1544f9..c6802d8f98c 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/consistency/impl/ObjectAlreadyExistHandler.java
@@ -108,7 +108,7 @@ public T handleError(T shadow, FailedOperation op, Except
changeNotificationDispatcher.notifyChange(change, task, operationResult);
}
} finally {
- operationResult.computeStatus();
+ operationResult.computeStatus();
}
if (operationResult.isSuccess()) {
parentResult.recordSuccess();
@@ -133,15 +133,6 @@ private ObjectQuery createQueryByIcfName(ShadowType shadow) throws SchemaExcepti
secondaryIdentifierFilters.add(equal);
}
OrFilter orSecondary = OrFilter.createOr((List)secondaryIdentifierFilters);
-// PrismProperty nameProperty = null;
-// if (secondaryIdentifiers.size() != 1){
-// nameProperty = shadow.getAttributes().asPrismContainerValue()
-// .findProperty(new QName(SchemaConstants.NS_ICF_SCHEMA, "name"));
-// } else {
-// nameProperty = secondaryIdentifiers.iterator().next();
-// }
-
-// EqualFilter nameFilter = EqualFilter.createEqual(new ItemPath(ShadowType.F_ATTRIBUTES, nameProperty.getDefinition().getName()),nameProperty);
RefFilter resourceRefFilter = RefFilter.createReferenceEqual(ShadowType.F_RESOURCE_REF, ShadowType.class,
prismContext, shadow.getResourceRef().getOid());
EqualFilter objectClassFilter = EqualFilter.createEqual(ShadowType.F_OBJECT_CLASS, ShadowType.class, prismContext,
diff --git a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java
index 36937c78166..58babc2b883 100644
--- a/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java
+++ b/provisioning/provisioning-impl/src/main/java/com/evolveum/midpoint/provisioning/util/ProvisioningUtil.java
@@ -76,7 +76,7 @@
import java.util.List;
public class ProvisioningUtil {
-
+
private static final QName FAKE_SCRIPT_ARGUMENT_NAME = new QName(SchemaConstants.NS_C, "arg");
private static final Trace LOGGER = TraceManager.getTrace(ProvisioningUtil.class);
@@ -119,12 +119,14 @@ public static void normalizeShadow(T shadow, OperationRes
}
}
-
- public static PolyString determineShadowName(ShadowType shadow) throws SchemaException {
+
+ public static PolyString determineShadowName(ShadowType shadow)
+ throws SchemaException {
return determineShadowName(shadow.asPrismObject());
}
-
- public static PolyString determineShadowName(PrismObject shadow) throws SchemaException {
+
+ public static PolyString determineShadowName(PrismObject shadow)
+ throws SchemaException {
String stringName = determineShadowStringName(shadow);
if (stringName == null) {
return null;
@@ -132,7 +134,8 @@ public static PolyString determineShadowName(PrismObject<
return new PolyString(stringName);
}
- public static String determineShadowStringName(PrismObject shadow) throws SchemaException {
+ public static String determineShadowStringName(PrismObject shadow)
+ throws SchemaException {
ResourceAttributeContainer attributesContainer = ShadowUtil.getAttributesContainer(shadow);
ResourceAttribute namingAttribute = attributesContainer.getNamingAttribute();
if (namingAttribute == null || namingAttribute.isEmpty()) {
@@ -151,8 +154,8 @@ public static String determineShadowStringName(PrismObjec
}
}
} else {
- return attributesContainer.findAttribute(ConnectorFactoryIcfImpl.ICFS_NAME).getValue(String.class)
- .getValue();
+ return attributesContainer.findAttribute(ConnectorFactoryIcfImpl.ICFS_NAME)
+ .getValue(String.class).getValue();
}
// Identifier is not usable as name
// TODO: better identification of a problem
@@ -160,91 +163,96 @@ public static String determineShadowStringName(PrismObjec
}
// TODO: Error handling
List> possibleValues = namingAttribute.getValues();
-
- if (possibleValues.size() > 1){
- throw new SchemaException("Cannot determine name of shadow. Found more than one value for naming attribute (attr: "+namingAttribute.getElementName()+", values: {}"+possibleValues+")" );
+
+ if (possibleValues.size() > 1) {
+ throw new SchemaException(
+ "Cannot determine name of shadow. Found more than one value for naming attribute (attr: "
+ + namingAttribute.getElementName() + ", values: {}" + possibleValues + ")");
}
-
+
PrismPropertyValue value = possibleValues.iterator().next();
-
- if (value == null){
+
+ if (value == null) {
throw new SchemaException("Naming attribute has no value. Could not determine shadow name.");
}
-
+
return value.getValue();
-// return attributesContainer.getNamingAttribute().getValue().getValue();
+ // return
+ // attributesContainer.getNamingAttribute().getValue().getValue();
}
-
-
public static PrismObjectDefinition getResourceObjectShadowDefinition(
PrismContext prismContext) {
return prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(ShadowType.class);
}
-
+
@SuppressWarnings("unchecked")
- public static String getResourceOidFromFilter(List extends ObjectFilter> conditions) throws SchemaException{
-
- for (ObjectFilter f : conditions){
- if (f instanceof RefFilter && ShadowType.F_RESOURCE_REF.equals(((RefFilter) f).getDefinition().getName())){
- List values = (List)((RefFilter) f).getValues();
- if (values.size() > 1){
- throw new SchemaException("More than one resource references defined in the search query.");
- }
- if (values.size() < 1){
- throw new SchemaException("Search query does not have specified resource reference.");
- }
- return values.get(0).getOid();
+ public static String getResourceOidFromFilter(List extends ObjectFilter> conditions)
+ throws SchemaException {
+
+ for (ObjectFilter f : conditions) {
+ if (f instanceof RefFilter
+ && ShadowType.F_RESOURCE_REF.equals(((RefFilter) f).getDefinition().getName())) {
+ List values = (List) ((RefFilter) f).getValues();
+ if (values.size() > 1) {
+ throw new SchemaException(
+ "More than one resource references defined in the search query.");
}
- if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())){
- String resourceOid = getResourceOidFromFilter(((NaryLogicalFilter) f).getConditions());
- if (resourceOid != null){
- return resourceOid;
- }
+ if (values.size() < 1) {
+ throw new SchemaException("Search query does not have specified resource reference.");
}
+ return values.get(0).getOid();
}
-
- return null;
-
+ if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())) {
+ String resourceOid = getResourceOidFromFilter(((NaryLogicalFilter) f).getConditions());
+ if (resourceOid != null) {
+ return resourceOid;
+ }
+ }
+ }
+
+ return null;
+
}
-
+
@SuppressWarnings("rawtypes")
- public static T getValueFromFilter(List extends ObjectFilter> conditions, QName propertyName) throws SchemaException{
- ItemPath propertyPath = new ItemPath(propertyName);
- for (ObjectFilter f : conditions){
- if (f instanceof EqualFilter && propertyPath.equivalent(((EqualFilter) f).getFullPath())){
- List extends PrismValue> values = ((EqualFilter) f).getValues();
- if (values.size() > 1){
- throw new SchemaException("More than one "+propertyName+" defined in the search query.");
- }
- if (values.size() < 1){
- throw new SchemaException("Search query does not have specified "+propertyName+".");
- }
-
- return (T) ((PrismPropertyValue)values.get(0)).getValue();
+ public static T getValueFromFilter(List extends ObjectFilter> conditions, QName propertyName)
+ throws SchemaException {
+ ItemPath propertyPath = new ItemPath(propertyName);
+ for (ObjectFilter f : conditions) {
+ if (f instanceof EqualFilter && propertyPath.equivalent(((EqualFilter) f).getFullPath())) {
+ List extends PrismValue> values = ((EqualFilter) f).getValues();
+ if (values.size() > 1) {
+ throw new SchemaException("More than one " + propertyName
+ + " defined in the search query.");
}
- if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())){
- T value = getValueFromFilter(((NaryLogicalFilter) f).getConditions(), propertyName);
- if (value != null){
- return value;
- }
+ if (values.size() < 1) {
+ throw new SchemaException("Search query does not have specified " + propertyName + ".");
}
+
+ return (T) ((PrismPropertyValue) values.get(0)).getValue();
}
-
- return null;
+ if (NaryLogicalFilter.class.isAssignableFrom(f.getClass())) {
+ T value = getValueFromFilter(((NaryLogicalFilter) f).getConditions(), propertyName);
+ if (value != null) {
+ return value;
+ }
+ }
+ }
+
+ return null;
}
-
- public static ExecuteProvisioningScriptOperation convertToScriptOperation(ProvisioningScriptType scriptType,
- String desc, PrismContext prismContext) throws SchemaException {
+
+ public static ExecuteProvisioningScriptOperation convertToScriptOperation(
+ ProvisioningScriptType scriptType, String desc, PrismContext prismContext) throws SchemaException {
ExecuteProvisioningScriptOperation scriptOperation = new ExecuteProvisioningScriptOperation();
- PrismPropertyDefinition scriptArgumentDefinition = new PrismPropertyDefinition(FAKE_SCRIPT_ARGUMENT_NAME,
- DOMUtil.XSD_STRING, prismContext);
-
+ PrismPropertyDefinition scriptArgumentDefinition = new PrismPropertyDefinition(
+ FAKE_SCRIPT_ARGUMENT_NAME, DOMUtil.XSD_STRING, prismContext);
+
for (ProvisioningScriptArgumentType argument : scriptType.getArgument()) {
ExecuteScriptArgument arg = new ExecuteScriptArgument(argument.getName(),
- StaticExpressionUtil.getStaticOutput(argument, scriptArgumentDefinition,
- desc,
+ StaticExpressionUtil.getStaticOutput(argument, scriptArgumentDefinition, desc,
ExpressionReturnMultiplicityType.SINGLE, prismContext));
scriptOperation.getArgument().add(arg);
}
@@ -260,61 +268,69 @@ public static ExecuteProvisioningScriptOperation convertToScriptOperation(Provis
scriptOperation.setConnectorHost(false);
scriptOperation.setResourceHost(true);
}
-
+
return scriptOperation;
}
-
- public static AttributesToReturn createAttributesToReturn(RefinedObjectClassDefinition objectClassDefinition,
- ResourceType resource) throws SchemaException {
+
+ public static AttributesToReturn createAttributesToReturn(
+ RefinedObjectClassDefinition objectClassDefinition, ResourceType resource) throws SchemaException {
boolean apply = false;
AttributesToReturn attributesToReturn = new AttributesToReturn();
attributesToReturn.setReturnDefaultAttributes(true);
-
+
// Attributes
Collection explicit = new ArrayList();
- for (RefinedAttributeDefinition attributeDefinition: objectClassDefinition.getAttributeDefinitions()) {
+ for (RefinedAttributeDefinition attributeDefinition : objectClassDefinition.getAttributeDefinitions()) {
AttributeFetchStrategyType fetchStrategy = attributeDefinition.getFetchStrategy();
if (fetchStrategy != null && fetchStrategy == AttributeFetchStrategyType.EXPLICIT) {
explicit.add(attributeDefinition);
}
}
-
+
if (!explicit.isEmpty()) {
attributesToReturn.setAttributesToReturn(explicit);
apply = true;
}
-
+
// Password
- CredentialsCapabilityType credentialsCapabilityType = ResourceTypeUtil.getEffectiveCapability(resource, CredentialsCapabilityType.class);
+ CredentialsCapabilityType credentialsCapabilityType = ResourceTypeUtil.getEffectiveCapability(
+ resource, CredentialsCapabilityType.class);
if (CapabilityUtil.isPasswordReturnedByDefault(credentialsCapabilityType)) {
- // There resource is capable of returning password but it does not do it by default
- AttributeFetchStrategyType passwordFetchStrategy = objectClassDefinition.getPasswordFetchStrategy();
+ // There resource is capable of returning password but it does not
+ // do it by default
+ AttributeFetchStrategyType passwordFetchStrategy = objectClassDefinition
+ .getPasswordFetchStrategy();
if (passwordFetchStrategy == AttributeFetchStrategyType.EXPLICIT) {
attributesToReturn.setReturnPasswordExplicit(true);
apply = true;
}
}
-
+
// Activation/administrativeStatus
- ActivationCapabilityType activationCapabilityType = ResourceTypeUtil.getEffectiveCapability(resource, ActivationCapabilityType.class);
+ ActivationCapabilityType activationCapabilityType = ResourceTypeUtil.getEffectiveCapability(resource,
+ ActivationCapabilityType.class);
if (CapabilityUtil.isActivationStatusReturnedByDefault(activationCapabilityType)) {
- // There resource is capable of returning enable flag but it does not do it by default
- AttributeFetchStrategyType administrativeStatusFetchStrategy = objectClassDefinition.getActivationFetchStrategy(ActivationType.F_ADMINISTRATIVE_STATUS);
+ // There resource is capable of returning enable flag but it does
+ // not do it by default
+ AttributeFetchStrategyType administrativeStatusFetchStrategy = objectClassDefinition
+ .getActivationFetchStrategy(ActivationType.F_ADMINISTRATIVE_STATUS);
if (administrativeStatusFetchStrategy == AttributeFetchStrategyType.EXPLICIT) {
attributesToReturn.setReturnAdministrativeStatusExplicit(true);
apply = true;
}
}
-
+
if (CapabilityUtil.isActivationLockoutStatusReturnedByDefault(activationCapabilityType)) {
- // There resource is capable of returning lockout flag but it does not do it by default
- AttributeFetchStrategyType statusFetchStrategy = objectClassDefinition.getActivationFetchStrategy(ActivationType.F_LOCKOUT_STATUS);
+ // There resource is capable of returning lockout flag but it does
+ // not do it by default
+ AttributeFetchStrategyType statusFetchStrategy = objectClassDefinition
+ .getActivationFetchStrategy(ActivationType.F_LOCKOUT_STATUS);
if (statusFetchStrategy == AttributeFetchStrategyType.EXPLICIT) {
attributesToReturn.setReturnLockoutStatusExplicit(true);
apply = true;
}
}
-
+
if (apply) {
return attributesToReturn;
} else {
From bdd71866f3b74a8de6210c84c01b6851230ada67 Mon Sep 17 00:00:00 2001
From: "Katarina Valalikova (katkav)"
Date: Sun, 5 Oct 2014 21:56:14 +0200
Subject: [PATCH 18/19] allow limit propagation only for already exists
sitaution
---
.../midpoint/model/impl/sync/SynchronizationService.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java
index 62424934432..8d5aab8ea39 100644
--- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java
+++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/sync/SynchronizationService.java
@@ -711,7 +711,7 @@ private Boolean determinePropagationLimitation(ObjectSynchronizationType synchro
// resource. We only want to resolve the problem and continue in
// previous provisioning/synchronization during which his
// compensation was triggered
- if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(channelQName)){
+ if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(channelQName) && SynchronizationSituationType.DELETED != reactionDefinition.getSituation()){
return true;
}
}
From 02accc61f98e76498f9ccbbc4e4560c53c21213c Mon Sep 17 00:00:00 2001
From: Pavol Mederly
Date: Mon, 6 Oct 2014 11:46:02 +0200
Subject: [PATCH 19/19] Attempt to correctly show model contexts with null
ResourceShadowDiscriminator.
---
.../progress/ProgressReportActivityDto.java | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/ProgressReportActivityDto.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/ProgressReportActivityDto.java
index d1424ea93ff..ea94694e639 100644
--- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/ProgressReportActivityDto.java
+++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/component/progress/ProgressReportActivityDto.java
@@ -95,10 +95,15 @@ public boolean correspondsTo(ProgressInformation newStatus) {
if (activityType != newStatus.getActivityType()) {
return false;
}
- if (activityType == RESOURCE_OBJECT_OPERATION
- && (resourceShadowDiscriminator == null ||
- !resourceShadowDiscriminator.equals(newStatus.getResourceShadowDiscriminator()))) {
- return false;
+ if (activityType == RESOURCE_OBJECT_OPERATION) {
+ if (resourceShadowDiscriminator != null &&
+ !resourceShadowDiscriminator.equals(newStatus.getResourceShadowDiscriminator())) {
+ return false;
+ }
+ if (resourceShadowDiscriminator == null && newStatus.getResourceShadowDiscriminator() != null) {
+ // actually, we consider all resource-related records with null RSD to be equal (even if they deal with different resources)
+ return false;
+ }
}
return true;
}