[prev in list] [next in list] [prev in thread] [next in thread]
List: forgerock-openidm-commit
Subject: [CommitOpenIDM] [5038] trunk: OPENIDM-2896/ OPENIDM-3053 CR-6432 Replace linkQualifier with queryFil
From: anonymous () forgerock ! org
Date: 2015-03-23 19:18:59
Message-ID: 20150323191859.112D33F865 () sources ! internal ! forgerock ! com
[Download RAW message or body]
[Attachment #2 (text/html)]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[5038] trunk: OPENIDM-2896/OPENIDM-3053 CR-6432 Replace linkQualifier with \
queryFilter in Conditions, use linkQualifiers to filter effectiveAssignments</title> \
</head> <body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: \
verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: \
bold} #msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: \
bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: \
6px; } #logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em \
0; } #logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg \
h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; } \
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; \
} #logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: \
-1.5em; padding-left: 1.5em; } #logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em \
1em 0 1em; background: white;} #logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid \
#fa0; border-bottom: 1px solid #fa0; background: #fff; } #logmsg table th { \
text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted \
#fa0; } #logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: \
0.2em 0.5em; } #logmsg table thead th { text-align: center; border-bottom: 1px solid \
#fa0; } #logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: \
6px; } #patch { width: 100%; }
#patch h4 {font-family: \
verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, \
#patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins \
{background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del \
{background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, \
.info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a \
href="http://sources.forgerock.org/changelog/openidm/?cs=5038">5038</a></dd> \
<dt>Author</dt> <dd>jbranch</dd> <dt>Date</dt> <dd>2015-03-23 19:18:58 +0000 (Mon, 23 \
Mar 2015)</dd> </dl>
<h3>Log Message</h3>
<pre><a href="https://bugster.forgerock.org/jira/browse/OPENIDM-2896">OPENIDM-2896</a>/<a \
href="https://bugster.forgerock.org/jira/browse/OPENIDM-3053">OPENIDM-3053</a> \
CR-6432 Replace linkQualifier with queryFilter in Conditions, use linkQualifiers to \
filter effectiveAssignments</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkopenidmcoresrcmainjavaorgforgerockopenidmsyncimplConditionjava">tru \
nk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/Condition.java</a></li> \
<li><a href="#trunkopenidmcoresrcmainjavaorgforgerockopenidmsyncimplObjectMappingjava" \
>trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/ObjectMapping.java</a></li>
>
<li><a href="#trunkopenidmcoresrcmainjavaorgforgerockopenidmsyncimplPropertyMappingjav \
a">trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/PropertyMapping.java</a></li>
<li><a href="#trunkopenidmcoresrctestjavaorgforgerockopenidmsyncimplPolicyTestjava">t \
runk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/PolicyTest.java</a></li>
<li><a href="#trunkopenidmcoresrctestresourcesconfsyncjson">trunk/openidm-core/src/test/resources/conf/sync.json</a></li>
<li><a href="#trunkopenidmzipsrcmainresourcesbindefaultsscriptrolesdefaultMappingjs"> \
trunk/openidm-zip/src/main/resources/bin/defaults/script/roles/defaultMapping.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkopenidmcoresrctestjavaorgforgerockopenidmsyncimplConditionTestjava" \
>trunk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/ConditionTest.java</a></li>
>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkopenidmcoresrcmainjavaorgforgerockopenidmsyncimplConditionjava"></a>
<div class="modfile"><h4>Modified: \
trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/Condition.java (5037 \
=> 5038)</h4> <pre class="diff"><span>
<span class="info">--- \
trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/Condition.java 2015-03-23 \
17:51:23 UTC (rev 5037)
+++ trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/Condition.java 2015-03-23 \
19:18:58 UTC (rev 5038) </span><span class="lines">@@ -23,17 +23,23 @@
</span><span class="cx"> */
</span><span class="cx"> package org.forgerock.openidm.sync.impl;
</span><span class="cx">
</span><del>-import java.util.HashMap;
-import java.util.Map;
-
</del><span class="cx"> import javax.script.ScriptException;
</span><span class="cx">
</span><ins>+import org.forgerock.json.fluent.JsonPointer;
</ins><span class="cx"> import org.forgerock.json.fluent.JsonValue;
</span><span class="cx"> import org.forgerock.json.fluent.JsonValueException;
</span><ins>+import org.forgerock.json.resource.QueryFilter;
+import org.forgerock.json.resource.QueryFilterVisitor;
</ins><span class="cx"> import org.forgerock.openidm.sync.impl.Scripts.Script;
</span><span class="cx"> import org.slf4j.Logger;
</span><span class="cx"> import org.slf4j.LoggerFactory;
</span><span class="cx">
</span><ins>+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
</ins><span class="cx"> /**
</span><span class="cx"> * Represents a condition on which a property mapping may be \
applied, or a policy may be enforced. </span><span class="cx"> */
</span><span class="lines">@@ -53,9 +59,9 @@
</span><span class="cx"> */
</span><span class="cx"> SCRIPTED,
</span><span class="cx"> /**
</span><del>- * A condition evaluated by a matching \
"linkQualifier". </del><ins>+ * A condition evaluated by a matching \
"queryFilter". </ins><span class="cx"> */
</span><del>- LINK_QUALIFIER,
</del><ins>+ QUERY_FILTER,
</ins><span class="cx"> /**
</span><span class="cx"> * A condition which always passes. This is used if \
a null configuration is passed in. </span><span class="cx"> */
</span><span class="lines">@@ -68,9 +74,9 @@
</span><span class="cx"> private Type type;
</span><span class="cx">
</span><span class="cx"> /**
</span><del>- * The link qualifier if configured
</del><ins>+ * The query filter if configured
</ins><span class="cx"> */
</span><del>- private String linkQualifier;
</del><ins>+ private QueryFilter queryFilter;
</ins><span class="cx">
</span><span class="cx"> /**
</span><span class="cx"> * The condition script if configured
</span><span class="lines">@@ -85,8 +91,8 @@
</span><span class="cx"> public Condition(JsonValue config) {
</span><span class="cx"> if (config.isNull()) {
</span><span class="cx"> init(Type.TRUE, null, null);
</span><del>- } else if \
(config.asMap().containsKey("linkQualifier")) {
- init(Type.LINK_QUALIFIER, \
config.get("linkQualifier").asString(), null); </del><ins>+ } else \
if (config.get("filter") != null) { + init(Type.QUERY_FILTER, \
QueryFilter.valueOf(config.get("filter").asString()), null); </ins><span \
class="cx"> } else { </span><span class="cx"> init(Type.SCRIPTED, \
null, Scripts.newInstance(config)); </span><span class="cx"> }
</span><span class="lines">@@ -96,12 +102,12 @@
</span><span class="cx"> * Initializes the condition fields.
</span><span class="cx"> *
</span><span class="cx"> * @param type the conditions type.
</span><del>- * @param linkQualifier the link qualifier.
</del><ins>+ * @param queryFilter the query filter.
</ins><span class="cx"> * @param script the condition script.
</span><span class="cx"> */
</span><del>- private void init(Type type, String linkQualifier, Script script) {
</del><ins>+ private void init(Type type, QueryFilter queryFilter, Script script) \
{ </ins><span class="cx"> this.type = type;
</span><del>- this.linkQualifier = linkQualifier;
</del><ins>+ this.queryFilter = queryFilter;
</ins><span class="cx"> this.script = script;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -109,20 +115,18 @@
</span><span class="cx"> * Evaluates the condition. Returns true if the \
condition is met, false otherwise. </span><span class="cx"> *
</span><span class="cx"> * @param params parameters to use during evaluation.
</span><del>- * @param linkQualifier the link qualifier associated with the \
current sync </del><span class="cx"> * @return true if the condition is met, \
false otherwise. </span><span class="cx"> * @throws SynchronizationException if \
errors are encountered. </span><span class="cx"> */
</span><del>- public boolean evaluate(JsonValue params, String linkQualifier)
</del><ins>+ public boolean evaluate(JsonValue params)
</ins><span class="cx"> throws SynchronizationException {
</span><span class="cx"> switch (type) {
</span><span class="cx"> case TRUE:
</span><span class="cx"> return true;
</span><del>- case LINK_QUALIFIER:
- return this.linkQualifier.equals(linkQualifier);
</del><ins>+ case QUERY_FILTER:
+ return queryFilter == null ? false : \
queryFilter.accept(JSONVALUE_FILTER_VISITOR, params); </ins><span class="cx"> \
case SCRIPTED: </span><span class="cx"> Map<String, Object> scope = \
new HashMap<String, Object>(); </span><del>- \
scope.put("linkQualifier", linkQualifier); </del><span class="cx"> \
try { </span><span class="cx"> if (params.isMap()) {
</span><span class="cx"> scope.putAll(params.asMap());
</span><span class="lines">@@ -143,4 +147,194 @@
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx"> }
</span><ins>+
+ /**
+ * This is a relatively generic implementation for testing JsonValue objects \
though it + * only returns Boolean for the test result. This may be extractable \
to a more common + * location for broader use.
+ */
+ private static final QueryFilterVisitor<Boolean, JsonValue> \
JSONVALUE_FILTER_VISITOR = + new QueryFilterVisitor<Boolean, \
JsonValue>() { +
+ @Override
+ public Boolean visitAndFilter(final JsonValue p, final \
List<QueryFilter> subFilters) { + for (final QueryFilter \
subFilter : subFilters) { + if (!subFilter.accept(this, p)) {
+ return Boolean.FALSE;
+ }
+ }
+ return Boolean.TRUE;
+ }
+
+ @Override
+ public Boolean visitBooleanLiteralFilter(final JsonValue p, final \
boolean value) { + return value;
+ }
+
+ @Override
+ public Boolean visitContainsFilter(final JsonValue p, final \
JsonPointer field, + final Object \
valueAssertion) { + for (final Object value : getValues(p, field)) \
{ + if (isCompatible(valueAssertion, value)) {
+ if (valueAssertion instanceof String) {
+ final String s1 = ((String) \
valueAssertion).toLowerCase(Locale.ENGLISH); + final \
String s2 = ((String) value).toLowerCase(Locale.ENGLISH); + \
if (s2.contains(s1)) { + return Boolean.TRUE;
+ }
+ } else {
+ // Use equality matching for numbers and booleans.
+ if (compareValues(valueAssertion, value) == 0) {
+ return Boolean.TRUE;
+ }
+ }
+ }
+ }
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public Boolean visitEqualsFilter(final JsonValue p, final \
JsonPointer field, + final Object \
valueAssertion) { + Boolean result = Boolean.TRUE;
+ for (final Object value : getValues(p, field)) {
+ if (!isCompatible(valueAssertion, value) || \
compareValues(valueAssertion, value) != 0) { + result = \
Boolean.FALSE; + }
+ }
+ return result;
+ }
+
+ @Override
+ public Boolean visitExtendedMatchFilter(final JsonValue p, final \
JsonPointer field, + final \
String matchingRuleId, final Object valueAssertion) { + // \
Extended filters are not supported + return Boolean.FALSE;
+ }
+
+ @Override
+ public Boolean visitGreaterThanFilter(final JsonValue p, final \
JsonPointer field, + final \
Object valueAssertion) { + for (final Object value : getValues(p, \
field)) { + if (isCompatible(valueAssertion, value) && \
compareValues(valueAssertion, value) < 0) { + return \
Boolean.TRUE; + }
+ }
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public Boolean visitGreaterThanOrEqualToFilter(final JsonValue p, \
final JsonPointer field, + \
final Object valueAssertion) { + for (final Object value : \
getValues(p, field)) { + if (isCompatible(valueAssertion, \
value) && compareValues(valueAssertion, value) <= 0) { + \
return Boolean.TRUE; + }
+ }
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public Boolean visitLessThanFilter(final JsonValue p, final \
JsonPointer field, + final Object \
valueAssertion) { + for (final Object value : getValues(p, field)) \
{ + if (isCompatible(valueAssertion, value) && \
compareValues(valueAssertion, value) > 0) { + return \
Boolean.TRUE; + }
+ }
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public Boolean visitLessThanOrEqualToFilter(final JsonValue p, final \
JsonPointer field, + final \
Object valueAssertion) { + for (final Object value : getValues(p, \
field)) { + if (isCompatible(valueAssertion, value) && \
compareValues(valueAssertion, value) >= 0) { + return \
Boolean.TRUE; + }
+ }
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public Boolean visitNotFilter(final JsonValue p, final QueryFilter \
subFilter) { + return !subFilter.accept(this, p);
+ }
+
+ @Override
+ public Boolean visitOrFilter(final JsonValue p, final \
List<QueryFilter> subFilters) { + for (final QueryFilter \
subFilter : subFilters) { + if (subFilter.accept(this, p)) {
+ return Boolean.TRUE;
+ }
+ }
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public Boolean visitPresentFilter(final JsonValue p, final \
JsonPointer field) { + final JsonValue value = p.get(field);
+ return value != null;
+ }
+
+ @Override
+ public Boolean visitStartsWithFilter(final JsonValue p, final \
JsonPointer field, + final Object \
valueAssertion) { + for (final Object value : getValues(p, field)) \
{ + if (isCompatible(valueAssertion, value)) {
+ if (valueAssertion instanceof String) {
+ final String s1 = ((String) \
valueAssertion).toLowerCase(Locale.ENGLISH); + final \
String s2 = ((String) value).toLowerCase(Locale.ENGLISH); + \
if (s2.startsWith(s1)) { + return Boolean.TRUE;
+ }
+ } else {
+ // Use equality matching for numbers and booleans.
+ if (compareValues(valueAssertion, value) == 0) {
+ return Boolean.TRUE;
+ }
+ }
+ }
+ }
+ return Boolean.FALSE;
+ }
+
+ private List<Object> getValues(final JsonValue resource, final \
JsonPointer field) { + final JsonValue value = \
resource.get(field); + if (value == null) {
+ return Collections.emptyList();
+ } else if (value.isList()) {
+ return value.asList();
+ } else {
+ return Collections.singletonList(value.getObject());
+ }
+ }
+
+ };
+
+ private static int compareValues(final Object v1, final Object v2) {
+ if (v1 instanceof String && v2 instanceof String) {
+ final String s1 = (String) v1;
+ final String s2 = (String) v2;
+ return s1.compareToIgnoreCase(s2);
+ } else if (v1 instanceof Number && v2 instanceof Number) {
+ final Double n1 = ((Number) v1).doubleValue();
+ final Double n2 = ((Number) v2).doubleValue();
+ return n1.compareTo(n2);
+ } else if (v1 instanceof Boolean && v2 instanceof Boolean) {
+ final Boolean b1 = (Boolean) v1;
+ final Boolean b2 = (Boolean) v2;
+ return b1.compareTo(b2);
+ } else {
+ // Different types: we need to ensure predictable ordering,
+ // so use class name as secondary key.
+ return v1.getClass().getName().compareTo(v2.getClass().getName());
+ }
+ }
+
+ private static boolean isCompatible(final Object v1, final Object v2) {
+ return (v1 instanceof String && v2 instanceof String)
+ || (v1 instanceof Number && v2 instanceof Number)
+ || (v1 instanceof Boolean && v2 instanceof Boolean);
+ }
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkopenidmcoresrcmainjavaorgforgerockopenidmsyncimplObjectMappingjava"></a>
<div class="modfile"><h4>Modified: \
trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/ObjectMapping.java \
(5037 => 5038)</h4> <pre class="diff"><span>
<span class="info">--- \
trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/ObjectMapping.java 2015-03-23 \
17:51:23 UTC (rev 5037)
+++ trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/ObjectMapping.java 2015-03-23 \
19:18:58 UTC (rev 5038) </span><span class="lines">@@ -666,7 +666,7 @@
</span><span class="cx"> property.apply(source, oldSource, target, \
linkQualifier); </span><span class="cx"> }
</span><span class="cx"> // Apply default mapping, if configured
</span><del>- applyDefaultMappings(source, oldSource, target, \
existingTarget); </del><ins>+ applyDefaultMappings(source, oldSource, \
target, existingTarget, linkQualifier); </ins><span class="cx">
</span><span class="cx"> measure.setResult(target);
</span><span class="cx"> } finally {
</span><span class="lines">@@ -674,7 +674,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- private JsonValue applyDefaultMappings(JsonValue source, JsonValue \
oldSource, JsonValue target, JsonValue existingTarget) throws \
SynchronizationException { </del><ins>+ private JsonValue \
applyDefaultMappings(JsonValue source, JsonValue oldSource, JsonValue target, \
JsonValue existingTarget, String linkQualifier) throws SynchronizationException { \
</ins><span class="cx"> JsonValue result = null; </span><span class="cx"> \
if (defaultMapping != null) { </span><span class="cx"> Map<String, \
Object> queryScope = new HashMap<String, Object>(); </span><span \
class="lines">@@ -685,6 +685,7 @@ </span><span class="cx"> \
queryScope.put("target", target.asMap()); </span><span class="cx"> \
queryScope.put("config", config.asMap()); </span><span class="cx"> \
queryScope.put("existingTarget", existingTarget.asMap()); </span><ins>+ \
queryScope.put("linkQualifier", linkQualifier); </ins><span class="cx"> \
try { </span><span class="cx"> result = \
json(defaultMapping.exec(queryScope)); </span><span class="cx"> } catch \
(ScriptThrownException ste) { </span><span class="lines">@@ -1708,7 +1709,10 @@
</span><span class="cx"> action = situation.getDefaultAction();
</span><span class="cx"> List<Policy> situationPolicies = \
getPolicies(situation); </span><span class="cx"> for (Policy policy : \
situationPolicies) { </span><del>- if \
(policy.getCondition().evaluate(json(field("object", getSourceObject())), \
getLinkQualifier())) { </del><ins>+ if \
(policy.getCondition().evaluate( + json(object(
+ field("object", getSourceObject()),
+ field("linkQualifier", \
getLinkQualifier()))))) { </ins><span class="cx"> \
activePolicy = policy; </span><span class="cx"> action = \
activePolicy.getAction(sourceObjectAccessor, </span><span class="cx"> \
targetObjectAccessor, this, getLinkQualifier()); </span></span></pre></div>
<a id="trunkopenidmcoresrcmainjavaorgforgerockopenidmsyncimplPropertyMappingjava"></a>
<div class="modfile"><h4>Modified: \
trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/PropertyMapping.java \
(5037 => 5038)</h4> <pre class="diff"><span>
<span class="info">--- \
trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/PropertyMapping.java 2015-03-23 \
17:51:23 UTC (rev 5037)
+++ trunk/openidm-core/src/main/java/org/forgerock/openidm/sync/impl/PropertyMapping.java 2015-03-23 \
19:18:58 UTC (rev 5038) </span><span class="lines">@@ -170,10 +170,10 @@
</span><span class="cx"> */
</span><span class="cx"> public boolean evaluateCondition(JsonValue sourceObject, \
JsonValue oldSource, JsonValue targetObject, String linkQualifier) </span><span \
class="cx"> throws SynchronizationException { </span><del>- \
JsonValue params = json(object(field("object", sourceObject))); \
</del><ins>+ JsonValue params = json(object(field("object", \
sourceObject), field("linkQualifier", linkQualifier))); </ins><span \
class="cx"> if (oldSource != null) { </span><span class="cx"> \
params.put("oldSource", oldSource); </span><span class="cx"> }
</span><del>- return condition.evaluate(params, linkQualifier);
</del><ins>+ return condition.evaluate(params);
</ins><span class="cx"> }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkopenidmcoresrctestjavaorgforgerockopenidmsyncimplConditionTestjava"></a>
<div class="addfile"><h4>Added: \
trunk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/ConditionTest.java \
(0 => 5038)</h4> <pre class="diff"><span>
<span class="info">--- \
trunk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/ConditionTest.java \
(rev 0)
+++ trunk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/ConditionTest.java 2015-03-23 \
19:18:58 UTC (rev 5038) </span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2014-2015 ForgeRock AS. All rights reserved.
+ *
+ * The contents of this file are subject to the terms
+ * of the Common Development and Distribution License
+ * (the License). You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ * http://forgerock.org/license/CDDLv1.0.html
+ * See the License for the specific language governing
+ * permission and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL
+ * Header Notice in each file and include the License file
+ * at http://forgerock.org/license/CDDLv1.0.html
+ * If applicable, add the following below the CDDL Header,
+ * with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ */
+package org.forgerock.openidm.sync.impl;
+
+import org.forgerock.json.fluent.JsonValue;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.HashMap;
+
+import static org.fest.assertions.api.Assertions.assertThat;
+import static org.forgerock.json.fluent.JsonValue.field;
+import static org.forgerock.json.fluent.JsonValue.json;
+import static org.forgerock.json.fluent.JsonValue.object;
+
+/**
+ * Test the Condition class.
+ *
+ * Currently only the filter visitor is tested.
+ */
+public class ConditionTest {
+ private static JsonValue testObject = json(object(
+ field("object", object(
+ field("name", "alice"),
+ field("age", 1234L),
+ field("balance", 3.14159),
+ field("isAdmin", false))
+ ),
+ field("linkQualifier", "test")));
+
+ @DataProvider
+ public Object[][] filterData() {
+ return new Object[][] {
+ // @formatter:off
+ { "/object/name eq \"alice\"", true },
+ { "/object/age eq 1234", true },
+ { "/object/balance eq 3.14159", true },
+ { "/object/isAdmin eq false", true },
+ { "/object/age lt 1234", false },
+ { "/object/age le 1234", true },
+ { "/object/age gt 1234", false },
+ { "/object/age ge 1234", true },
+ { "/object/name co \"al\"", true },
+ { "/object/name sw \"al\"", true },
+ { "/object/name pr", true },
+ { "/object/age lt 18 or /object/age gt 30", true },
+ { "/object/age lt 1000 or /object/age gt 3000", false },
+ { "/object/age lt 18 and /object/age gt 30", false },
+ { "/object/age gt 1000 and /object/age lt 1300", true },
+ { "/object/age ne 1234", false },
+ { "/linkQualifier eq \"test\"", true },
+ { "/linkQualifier eq \"fail\"", false }
+ // @formatter:on
+ };
+ }
+
+ @Test(dataProvider = "filterData")
+ public void testEvaluate(String filter, Boolean state) throws \
SynchronizationException { + Condition testCondition = new \
Condition(json(object(field("filter", filter)))); + \
assertThat(testCondition.evaluate(testObject)).isEqualTo(state); + }
+}
</ins></span></pre></div>
<a id="trunkopenidmcoresrctestjavaorgforgerockopenidmsyncimplPolicyTestjava"></a>
<div class="modfile"><h4>Modified: \
trunk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/PolicyTest.java \
(5037 => 5038)</h4> <pre class="diff"><span>
<span class="info">--- \
trunk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/PolicyTest.java 2015-03-23 \
17:51:23 UTC (rev 5037)
+++ trunk/openidm-core/src/test/java/org/forgerock/openidm/sync/impl/PolicyTest.java 2015-03-23 \
19:18:58 UTC (rev 5038) </span><span class="lines">@@ -1,3 +1,26 @@
</span><ins>+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2014-2015 ForgeRock AS. All rights reserved.
+ *
+ * The contents of this file are subject to the terms
+ * of the Common Development and Distribution License
+ * (the License). You may not use this file except in
+ * compliance with the License.
+ *
+ * You can obtain a copy of the License at
+ * http://forgerock.org/license/CDDLv1.0.html
+ * See the License for the specific language governing
+ * permission and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL
+ * Header Notice in each file and include the License file
+ * at http://forgerock.org/license/CDDLv1.0.html
+ * If applicable, add the following below the CDDL Header,
+ * with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ */
</ins><span class="cx"> package org.forgerock.openidm.sync.impl;
</span><span class="cx">
</span><span class="cx"> import com.fasterxml.jackson.databind.ObjectMapper;
</span><span class="lines">@@ -20,6 +43,7 @@
</span><span class="cx"> import java.util.List;
</span><span class="cx"> import java.util.Map;
</span><span class="cx">
</span><ins>+import static org.forgerock.json.fluent.JsonValue.field;
</ins><span class="cx"> import static org.forgerock.json.fluent.JsonValue.json;
</span><span class="cx"> import static org.forgerock.json.fluent.JsonValue.object;
</span><span class="cx"> import static org.mockito.Matchers.anyMap;
</span><span class="lines">@@ -73,29 +97,29 @@
</span><span class="cx"> assertEquals(policies.size(), 8);
</span><span class="cx">
</span><span class="cx"> \
assertTrue(getPolicy(Situation.CONFIRMED).getCondition() </span><del>- \
.evaluate(json(object()), Link.DEFAULT_LINK_QUALIFIER)); </del><ins>+ \
.evaluate(json(object(field("linkQualifier", \
Link.DEFAULT_LINK_QUALIFIER))))); </ins><span class="cx">
</span><span class="cx"> assertTrue(getPolicy(Situation.FOUND).getCondition()
</span><del>- .evaluate(json(object()), Link.DEFAULT_LINK_QUALIFIER));
</del><ins>+ .evaluate(json(object(field("linkQualifier", \
Link.DEFAULT_LINK_QUALIFIER))))); </ins><span class="cx">
</span><span class="cx"> \
assertEquals((policies.get(Situation.ABSENT.toString())).size(), 2); </span><span \
class="cx"> assertTrue(getPolicy(Situation.ABSENT).getCondition() \
</span><del>- .evaluate(json(object()), "user")); \
</del><ins>+ .evaluate(json(object(field("linkQualifier", \
"user"))))); </ins><span class="cx">
</span><span class="cx"> \
assertTrue(getPolicy(Situation.AMBIGUOUS).getCondition() </span><del>- \
.evaluate(json(object()), Link.DEFAULT_LINK_QUALIFIER)); </del><ins>+ \
.evaluate(json(object(field("linkQualifier", \
Link.DEFAULT_LINK_QUALIFIER))))); </ins><span class="cx">
</span><span class="cx"> \
assertTrue(getPolicy(Situation.MISSING).getCondition() </span><del>- \
.evaluate(json(object()), Link.DEFAULT_LINK_QUALIFIER)); </del><ins>+ \
.evaluate(json(object(field("linkQualifier", \
Link.DEFAULT_LINK_QUALIFIER))))); </ins><span class="cx">
</span><span class="cx"> \
assertTrue(getPolicy(Situation.SOURCE_MISSING).getCondition() </span><del>- \
.evaluate(json(object()), Link.DEFAULT_LINK_QUALIFIER)); </del><ins>+ \
.evaluate(json(object(field("linkQualifier", \
Link.DEFAULT_LINK_QUALIFIER))))); </ins><span class="cx">
</span><span class="cx"> \
assertTrue(getPolicy(Situation.UNQUALIFIED).getCondition() </span><del>- \
.evaluate(json(object()), Link.DEFAULT_LINK_QUALIFIER)); </del><ins>+ \
.evaluate(json(object(field("linkQualifier", \
Link.DEFAULT_LINK_QUALIFIER))))); </ins><span class="cx">
</span><span class="cx"> \
assertTrue(getPolicy(Situation.UNASSIGNED).getCondition() </span><del>- \
.evaluate(json(object()), Link.DEFAULT_LINK_QUALIFIER)); </del><ins>+ \
.evaluate(json(object(field("linkQualifier", \
Link.DEFAULT_LINK_QUALIFIER))))); </ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> @Test
</span></span></pre></div>
<a id="trunkopenidmcoresrctestresourcesconfsyncjson"></a>
<div class="modfile"><h4>Modified: \
trunk/openidm-core/src/test/resources/conf/sync.json (5037 => 5038)</h4> <pre \
class="diff"><span> <span class="info">--- \
trunk/openidm-core/src/test/resources/conf/sync.json 2015-03-23 17:51:23 UTC (rev \
5037)
+++ trunk/openidm-core/src/test/resources/conf/sync.json 2015-03-23 19:18:58 UTC (rev \
5038) </span><span class="lines">@@ -33,7 +33,7 @@
</span><span class="cx"> },
</span><span class="cx"> {
</span><span class="cx"> "condition" : {
</span><del>- "linkQualifier": "user"
</del><ins>+ "filter": "/linkQualifier eq \
\"user\"" </ins><span class="cx"> },
</span><span class="cx"> "situation" : \
"ABSENT", </span><span class="cx"> "action" : \
"IGNORE", </span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> },
</span><span class="cx"> {
</span><span class="cx"> "condition" : {
</span><del>- "linkQualifier": "test"
</del><ins>+ "filter" : "/linkQualifier eq \
\"test\"" </ins><span class="cx"> },
</span><span class="cx"> "situation" : \
"ABSENT", </span><span class="cx"> "action" : \
"CREATE", </span></span></pre></div>
<a id="trunkopenidmzipsrcmainresourcesbindefaultsscriptrolesdefaultMappingjs"></a>
<div class="modfile"><h4>Modified: \
trunk/openidm-zip/src/main/resources/bin/defaults/script/roles/defaultMapping.js \
(5037 => 5038)</h4> <pre class="diff"><span>
<span class="info">--- \
trunk/openidm-zip/src/main/resources/bin/defaults/script/roles/defaultMapping.js 2015-03-23 \
17:51:23 UTC (rev 5037)
+++ trunk/openidm-zip/src/main/resources/bin/defaults/script/roles/defaultMapping.js 2015-03-23 \
19:18:58 UTC (rev 5038) </span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /**
</span><span class="cx"> * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
</span><span class="cx"> *
</span><del>- * Copyright (c) 2014 ForgeRock AS. All rights reserved.
</del><ins>+ * Copyright (c) 2014-2015 ForgeRock AS. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * The contents of this file are subject to the terms
</span><span class="cx"> * of the Common Development and Distribution License
</span><span class="lines">@@ -99,6 +99,7 @@
</span><span class="cx"> scope.sourceObject = source;
</span><span class="cx"> scope.targetObject = target;
</span><span class="cx"> scope.existingTargetObject = existingTarget;
</span><ins>+ scope.linkQualifier = linkQualifier;
</ins><span class="cx"> for (var key in config) {
</span><span class="cx"> scope[key] = config[key];
</span><span class="cx"> }
</span><span class="lines">@@ -199,36 +200,42 @@
</span><span class="cx"> var assignment = effectiveAssignments[key];
</span><span class="cx"> var attributes = assignment.attributes;
</span><span class="cx"> var onAssignment = assignment.onAssignment;
</span><del>- // Check if an onAssignment script is configured
- if (typeof onAssignment !== 'undefined' && onAssignment !== \
null) {
- onAssignment.attributes = attributes;
- execOnScript(onAssignment);
- }
</del><span class="cx">
</span><del>- // Used to carry information across different \
assignmentOperations
- var attributesInfo = {};
- // Loop through attributes, performing the assignementOperations
- for (var i = 0; i < attributes.length; i++) {
- var attribute = attributes[i];
- var assignmentOperation = attribute.assignmentOperation;
- var value = attribute.value;
- var name = attribute.name;
- if (assignmentOperation == null) {
- // Default to replace and use the entire value
- assignmentOperation = defaultAssignmentOperation;
</del><ins>+ // Only map if no linkQualifier was specified or the \
linkQualifier matches the assignment + if (typeof linkQualifier === \
'undefined' || linkQualifier === null + || \
assignment.linkQualifiers.indexOf(linkQualifier) > -1) { +
+ // Check if an onAssignment script is configured
+ if (typeof onAssignment !== 'undefined' && onAssignment \
!== null) { + onAssignment.attributes = attributes;
+ execOnScript(onAssignment);
</ins><span class="cx"> }
</span><del>- // Process the assignmentOperation
- var config = getConfig(assignmentOperation);
- config.attributeName = name;
- config.attributeValue = value;
- config.attributesInfo = attributesInfo;
- // The result of this call should be an object with a field \
"value" contianing the updated target field's value
- var assignmentResult = openidm.action("script", \
"eval", config, {});
- // Set the new target field's value
- target[name] = assignmentResult.value;
- // Update any passed back attributesInfo
- if (assignmentResult.hasOwnProperty("attributesInfo")) \
{
- attributesInfo = assignmentResult.attributesInfo;
</del><ins>+
+ // Used to carry information across different \
assignmentOperations + var attributesInfo = {};
+ // Loop through attributes, performing the assignmentOperations
+ for (var i = 0; i < attributes.length; i++) {
+ var attribute = attributes[i];
+ var assignmentOperation = attribute.assignmentOperation;
+ var value = attribute.value;
+ var name = attribute.name;
+ if (assignmentOperation == null) {
+ // Default to replace and use the entire value
+ assignmentOperation = defaultAssignmentOperation;
+ }
+ // Process the assignmentOperation
+ var config = getConfig(assignmentOperation);
+ config.attributeName = name;
+ config.attributeValue = value;
+ config.attributesInfo = attributesInfo;
+ // The result of this call should be an object with a field \
"value" containing the updated target field's value + \
var assignmentResult = openidm.action("script", "eval", config, \
{}); + // Set the new target field's value
+ target[name] = assignmentResult.value;
+ // Update any passed back attributesInfo
+ if \
(assignmentResult.hasOwnProperty("attributesInfo")) { + \
attributesInfo = assignmentResult.attributesInfo; + }
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
<div id="footer">Copyright (c) by ForgeRock. All rights reserved.</div>
</body>
</html>
_______________________________________________
CommitOpenIDM mailing list
CommitOpenIDM@forgerock.org
https://lists.forgerock.org/mailman/listinfo/commitopenidm
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic