You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/06/11 16:17:35 UTC
[45/70] syncope git commit: [SYNCOPE-666] All tests are green,
time to add more
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
index c592c31..a75e4b6 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
@@ -312,6 +312,56 @@ under the License.
</attributes>
</entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADerAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_ADerAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_ADerAttr" pk-column-value="SEQ_ADerAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_UDerAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_UDerAttr" pk-column-value="SEQ_UDerAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_GDerAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_GDerAttr" pk-column-value="SEQ_GDerAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+
<entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPAAnyTemplate">
<attributes>
<id name="id">
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
index 746314c..6f83543 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
@@ -360,6 +360,56 @@ under the License.
</attributes>
</entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADerAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_ADerAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_ADerAttr" pk-column-value="SEQ_ADerAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_UDerAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_UDerAttr" pk-column-value="SEQ_UDerAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_GDerAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_GDerAttr" pk-column-value="SEQ_GDerAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+ <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
+ <attributes>
+ <id name="id">
+ <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
+ <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
+ </id>
+ </attributes>
+ </entity>
+
<entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPAAnyTemplate">
<attributes>
<id name="id">
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
index e1ffc11..02815b8 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
@@ -60,7 +60,7 @@ public class VirAttrTest extends AbstractTest {
@Test
public void findById() {
- UVirAttr attribute = virAttrDAO.find(1000L, UVirAttr.class);
+ UVirAttr attribute = virAttrDAO.find(100L, UVirAttr.class);
assertNotNull("did not find expected attribute schema", attribute);
}
@@ -104,7 +104,7 @@ public class VirAttrTest extends AbstractTest {
@Test
public void delete() {
- UVirAttr attribute = virAttrDAO.find(1000L, UVirAttr.class);
+ UVirAttr attribute = virAttrDAO.find(100L, UVirAttr.class);
String attributeSchemaName = attribute.getSchema().getKey();
virAttrDAO.delete(attribute.getKey(), UVirAttr.class);
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
index e6a919d..60ff041 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
@@ -52,13 +52,8 @@ public class AnyTypeTest extends AbstractTest {
anyTypeClassDAO.delete("other");
- try {
anyTypeDAO.flush();
- } catch(Exception e) {
- System.err.println("EEEEEEEEEEEE");
- e.printStackTrace();
- }
-
+
userType = anyTypeDAO.findUser();
assertNotNull(userType);
assertEquals(before, userType.getClasses().size() + 1);
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/test/resources/content.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/content.xml b/core/persistence-jpa/src/test/resources/content.xml
index 8d2ef54..7c123a7 100644
--- a/core/persistence-jpa/src/test/resources/content.xml
+++ b/core/persistence-jpa/src/test/resources/content.xml
@@ -94,11 +94,11 @@ under the License.
<!-- sample policies -->
<Policy DTYPE="SyncPolicy" id="1" description="a sync policy" type="SYNC"
- specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"groupAltSearchSchemas":[]}'/>
+ specification='{"conflictResolutionAction":"IGNORE","items":[]}'/>
<Policy DTYPE="PasswordPolicy" id="2" description="a password policy" type="PASSWORD"
specification='{"historyLength":1,"maxLength":0,"minLength":8,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":false,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[],"allowNullPassword":true}'/>
<Policy DTYPE="SyncPolicy" id="3" description="sync policy 2" type="SYNC"
- specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"ALL","userAltSearchSchemas":["username","firstname"],"groupAltSearchSchemas":[]}'/>
+ specification='{"conflictResolutionAction":"ALL","items":[{"anyTypeKey":"USER","javaRule":null,"altSearchSchemas":["username","firstname"]}]}'/>
<Policy DTYPE="PasswordPolicy" id="4" description="sample password policy" type="PASSWORD"
specification='{"historyLength":0,"maxLength":0,"minLength":10,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[], "allowNullPassword":true}'/>
<Policy DTYPE="AccountPolicy" id="5" description="an account policy" type="ACCOUNT"
@@ -106,11 +106,11 @@ under the License.
<Policy DTYPE="AccountPolicy" id="6" description="sample account policy" type="ACCOUNT"
specification='{"maxLength":0,"minLength":4,"pattern":null,"allUpperCase":false,"allLowerCase":false,"propagateSuspension":false,"maxAuthenticationAttempts":3,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
<Policy DTYPE="SyncPolicy" id="7" description="sync policy 1" type="SYNC"
- specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"groupAltSearchSchemas":[]}'/>
+ specification='{"conflictResolutionAction":"IGNORE","items":[]}'/>
<Policy DTYPE="PasswordPolicy" id="8" description="sample password policy" type="PASSWORD"
specification='{"historyLength":0,"maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[],"allowNullPassword":false}'/>
<Policy DTYPE="SyncPolicy" id="9" description="sync policy for java rule" type="SYNC"
- specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"groupAltSearchSchemas":[]}'/>
+ specification='{"conflictResolutionAction":"IGNORE","items":[]}'/>
<AnyTypeClass name="generic membership"/>
@@ -307,6 +307,7 @@ under the License.
<DerSchema name="noschema" expression="surname + ', ' + notfound" anyTypeClass_name="other"/>
<VirSchema name="virtualdata" anyTypeClass_name="minimal user"/>
+ <VirSchema name="virtualReadOnly" READONLY="1" anyTypeClass_name="minimal user"/>
<PlainSchema name="icon" type="String" anyTypeClass_name="minimal group"
mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
@@ -328,7 +329,7 @@ under the License.
<VirSchema name="rvirtualdata" anyTypeClass_name="minimal group"/>
- <DerSchema name="rderivedschema" expression="rderived_sx + '-' + rderived_dx"/>
+ <DerSchema name="rderivedschema" expression="rderived_sx + '-' + rderived_dx" anyTypeClass_name="minimal group"/>
<PlainSchema name="subscriptionDate" type="Date" anyTypeClass_name="generic membership"
mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
@@ -412,9 +413,7 @@ under the License.
<UPlainAttr id="126" owner_id="3" schema_name="type"/>
<UPlainAttrValue id="37" attribute_id="126" stringValue="F"/>
- <UVirAttr id="1000" schema_name="virtualdata" owner_id="3"/>
-
- <VirSchema name="virtualReadOnly" READONLY="1"/>
+ <UVirAttr id="100" schema_name="virtualdata" owner_id="3"/>
<UDerAttr id="100" schema_name="cn" owner_id="3"/>
<UDerAttr id="101" schema_name="cn" owner_id="1"/>
@@ -446,13 +445,13 @@ under the License.
<GPlainAttr id="995" owner_id="13" schema_name="title"/>
<GPlainAttrValue attribute_id="995" id="95" stringValue="r13"/>
- <GDerAttr id="1000" owner_id="1" schema_name="rderiveddata"/>
+ <GDerAttr id="100" owner_id="1" schema_name="rderiveddata"/>
- <GDerAttr id="1001" owner_id="1" schema_name="displayProperty"/>
+ <GDerAttr id="101" owner_id="1" schema_name="displayProperty"/>
- <GDerAttr id="1002" owner_id="4" schema_name="displayProperty"/>
+ <GDerAttr id="102" owner_id="4" schema_name="displayProperty"/>
- <GDerAttr id="1003" owner_id="1" schema_name="rderToBePropagated"/>
+ <GDerAttr id="103" owner_id="1" schema_name="rderToBePropagated"/>
<GVirAttr id="98" owner_id="4" schema_name="rvirtualdata"/>
@@ -816,10 +815,10 @@ under the License.
connObjectKey="1" password="0" purpose="BOTH"/>
<MappingItem id="208" extAttrName="theirgroup" mapping_id="9"
intAttrName="rderToBePropagated" intMappingType="GroupDerivedSchema" mandatoryCondition="false"
- connObjectKey="0" password="0" purpose="BOTH"/>
+ connObjectKey="0" password="0" purpose="PROPAGATION"/>
<MappingItem id="209" extAttrName="membership" mapping_id="9"
intAttrName="mderToBePropagated" intMappingType="AnyDerivedSchema" mandatoryCondition="false"
- connObjectKey="0" password="0" purpose="BOTH"/>
+ connObjectKey="0" password="0" purpose="PROPAGATION"/>
<Provision id="10" resource_name="ws-target-resource-update-resetsynctoken" anyType_name="USER" objectClass="__ACCOUNT__"
serializedSyncToken='{"value":null}'/>
@@ -853,7 +852,7 @@ under the License.
extAttrName="title" intAttrName="title" intMappingType="GroupPlainSchema"
mandatoryCondition="false" purpose="BOTH"/>
<MappingItem id="317" connObjectKey="0" password="0" mapping_id="11"
- extAttrName="postalAddress" intAttrName="postalAddress" intMappingType="AnyPlainSchema"
+ extAttrName="postalAddress" intAttrName="postalAddress" intMappingType="UserPlainSchema"
mandatoryCondition="false" purpose="BOTH"/>
<MappingItem id="318" connObjectKey="0" password="0" mapping_id="11"
extAttrName="mail" intAttrName="userId" intMappingType="UserPlainSchema"
@@ -940,9 +939,9 @@ under the License.
destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="ASSIGN" matchingRule="UPDATE"/>
<AnyTemplate id="41" syncTask_id="4" anyType_name="USER"
- template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == 'test8@syncope.apache.org'? 'TYPE_8': 'TYPE_OTHER'"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["'2009-08-18T16:33:12.203+0200'"]}],"derAttrs":[],"virAttrs":[]}]}'/>
+ template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":["csv"],"derAttrs":[{"schema":"cn","readonly":false,"values":[""]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"relationships":[],"memberships":[{"leftType":null,"leftKey":0,"rightType":"GROUP","rightKey":8,"groupName":null}],"dynGroups":[],"roles":[],"dynRoles":[],"plainAttrs":[{"schema":"type","readonly":false,"values":["email == 'test8@syncope.apache.org'? 'TYPE_8': 'TYPE_OTHER'"]}]}'/>
<AnyTemplate id="42" syncTask_id="4" anyType_name="GROUP"
- template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+ template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[]}'/>
<Task DTYPE="SchedTask" type="SCHEDULED" id="5" name="SampleJob Task" jobClassName="org.apache.syncope.core.provisioning.java.job.SampleJob" cronExpression="0 0 0 1 * ?"/>
<Task DTYPE="PropagationTask" type="PROPAGATION" id="6" propagationMode="TWO_PHASES" propagationOperation="UPDATE"
objectClassName="__ACCOUNT__" resource_name="ws-target-resource-nopropagation" anyTypeKind="USER" anyKey="1"
@@ -951,10 +950,10 @@ under the License.
<Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="7" name="TestDB Task" resource_name="resource-testdb"
destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" fullReconciliation="1"
jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
- <AnyTemplate id="61" syncTask_id="7" anyType_name="USER"
- template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == 'test8@syncope.apache.org'? 'TYPE_8': 'TYPE_OTHER'"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["'2009-08-18T16:33:12.203+0200'"]}],"derAttrs":[],"virAttrs":[]}]}'/>
- <AnyTemplate id="62" syncTask_id="7" anyType_name="GROUP"
- template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+ <AnyTemplate id="71" syncTask_id="7" anyType_name="USER"
+ template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"relationships":[],"memberships":[],"dynGroups":[],"roles":[],"dynRoles":[],"plainAttrs":[{"schema":"type","readonly":false,"values":["'type a'"]},{"schema":"userId","readonly":false,"values":["'reconciled@syncope.apache.org'"]},{"schema":"fullname","readonly":false,"values":["'reconciled fullname'"]},{"schema":"surname","readonly":false,"values":["'surname'"]}]}'/>
+ <AnyTemplate id="72" syncTask_id="7" anyType_name="GROUP"
+ template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[]}'/>
<Task DTYPE="NotificationTask" type="NOTIFICATION" id="8" sender="admin@prova.org" subject="Notification for SYNCOPE-81"
textBody="NOTIFICATION-81" htmlBody="NOTIFICATION-81" traceLevel="ALL"/>
<Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="9" name="TestDB2 Task" resource_name="resource-testdb2"
@@ -967,9 +966,9 @@ under the License.
destinationRealm_id="1" fullReconciliation="1" performCreate="1" performDelete="1" performUpdate="1" syncStatus="0"
jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
<AnyTemplate id="1" syncTask_id="11" anyType_name="USER"
- template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == 'test8@syncope.apache.org'? 'TYPE_8': 'TYPE_OTHER'"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["'2009-08-18T16:33:12.203+0200'"]}],"derAttrs":[],"virAttrs":[]}]}'/>
+ template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[{"schema":"virtualReadOnly","readonly":true,"values":[""]}],"resources":["resource-ldap"],"propagationStatuses":[],"roles":[],"dynRoles":[],"relationships":[],"memberships":[],"dynGroups":[],"plainAttrs":[]}'/>
<AnyTemplate id="2" syncTask_id="11" anyType_name="GROUP"
- template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+ template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[{"schema":"show","readonly":false,"values":["true"]}]}'/>
<SyncTask_actionsClassNames SyncTask_id="11" actionClassName="org.apache.syncope.core.provisioning.java.sync.LDAPMembershipSyncActions"/>
<Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="12" name="VirAttrCache test" resource_name="resource-csv"
destinationRealm_id="1" performCreate="0" performUpdate="1" performDelete="0" syncStatus="0" fullReconciliation="1"
@@ -1044,9 +1043,9 @@ under the License.
destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
<AnyTemplate id="3" syncTask_id="24" anyType_name="USER"
- template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == 'test8@syncope.apache.org'? 'TYPE_8': 'TYPE_OTHER'"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["'2009-08-18T16:33:12.203+0200'"]}],"derAttrs":[],"virAttrs":[]}]}'/>
+ template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"roles":[],"dynRoles":[],"relationships":[],"memberships":[],"dynGroups":[],"plainAttrs":[{"schema":"firstname","readonly":false,"values":[""]},{"schema":"userId","readonly":false,"values":["'test'"]},{"schema":"fullname","readonly":false,"values":["'test'"]},{"schema":"surname","readonly":false,"values":["'test'"]}]}'/>
<AnyTemplate id="4" syncTask_id="24" anyType_name="GROUP"
- template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+ template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[]}'/>
<Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="25" name="CSV (unlink matching; ignore unmatching)" resource_name="resource-csv"
destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="IGNORE" matchingRule="UNLINK"/>
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
new file mode 100644
index 0000000..4cec074
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.api;
+
+import java.util.Collection;
+import java.util.Set;
+import org.apache.syncope.common.lib.mod.AttrMod;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+
+public interface VirAttrHandler {
+
+ PropagationByResource fillVirtual(Any any, Set<String> vAttrsToBeRemoved, Set<AttrMod> vAttrsToBeUpdated);
+
+ /**
+ * Add virtual attributes and specify values to be propagated.
+ *
+ * @param any any.
+ * @param vAttrs virtual attributes to be added.
+ */
+ void fillVirtual(Any any, Collection<AttrTO> vAttrs);
+
+ /**
+ * SYNCOPE-459: build virtual attribute changes in case no other changes were made.
+ *
+ * @param key any key
+ * @param anyTypeKind type kind
+ * @param vAttrsToBeRemoved virtual attributes to be removed.
+ * @param vAttrsToBeUpdated virtual attributes to be updated.
+ * @return operations to be performed on external resources for virtual attributes changes
+ */
+ PropagationByResource fillVirtual(
+ Long key, AnyTypeKind anyTypeKind, Set<String> vAttrsToBeRemoved, Set<AttrMod> vAttrsToBeUpdated);
+
+ VirSchema getVirSchema(String virSchemaName);
+
+ /**
+ * Query connected external resources for values to populated virtual attributes associated with the given owner.
+ *
+ * @param any any object
+ */
+ void retrieveVirAttrValues(Any<?, ?, ?> any);
+
+ void updateOnResourcesIfMappingMatches(
+ Any<?, ?, ?> any, AnyUtils anyUtils, String schemaKey,
+ Iterable<? extends ExternalResource> resources, IntMappingType mappingType,
+ PropagationByResource propByRes);
+
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java
new file mode 100644
index 0000000..18187be
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.api.data;
+
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+
+public interface AnyTypeClassDataBinder {
+
+ AnyTypeClass create(AnyTypeClassTO anyTypeClassTO);
+
+ void update(AnyTypeClass anyTypeClass, AnyTypeClassTO anyTypeClassTO);
+
+ AnyTypeClassTO getAnyTypeClassTO(AnyTypeClass anyTypeClass);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java
new file mode 100644
index 0000000..c29c2ac
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.api.data;
+
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+
+public interface AnyTypeDataBinder {
+
+ AnyType create(AnyTypeTO anyTypeTO);
+
+ void update(AnyType anyType, AnyTypeTO anyTypeTO);
+
+ AnyTypeTO getAnyTypeTO(AnyType anyType);
+}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
index 1bd2638..fd6bcf1 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
@@ -30,6 +30,8 @@ import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.common.lib.mod.AnyObjectMod;
import org.apache.syncope.common.lib.to.PropagationStatus;
import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PropagationByResource;
import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
import org.apache.syncope.core.provisioning.api.AnyObjectProvisioningManager;
@@ -40,6 +42,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
import org.apache.syncope.core.workflow.api.AnyObjectWorkflowAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -102,6 +105,18 @@ public class DefaultAnyObjectProvisioningManager implements AnyObjectProvisionin
List<PropagationTask> tasks = propagationManager.getAnyObjectUpdateTasks(updated,
anyObjectMod.getVirAttrsToRemove(), anyObjectMod.getVirAttrsToUpdate(), null);
+ if (tasks.isEmpty()) {
+ // SYNCOPE-459: take care of user virtual attributes ...
+ PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
+ updated.getResult(),
+ AnyTypeKind.ANY_OBJECT,
+ anyObjectMod.getVirAttrsToRemove(),
+ anyObjectMod.getVirAttrsToUpdate());
+ tasks.addAll(!propByResVirAttr.isEmpty()
+ ? propagationManager.getAnyObjectUpdateTasks(updated, null, null, null)
+ : Collections.<PropagationTask>emptyList());
+ }
+
PropagationReporter propagationReporter =
ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
try {
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
index c7bc1c4..5661df4 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
@@ -36,6 +36,7 @@ import org.apache.syncope.common.lib.mod.GroupMod;
import org.apache.syncope.common.lib.to.AttrTO;
import org.apache.syncope.common.lib.to.PropagationStatus;
import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.PropagationByResource;
import org.apache.syncope.core.persistence.api.dao.GroupDAO;
import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -47,6 +48,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter;
public class DefaultGroupProvisioningManager implements GroupProvisioningManager {
@@ -65,6 +67,9 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
@Autowired
protected GroupDAO groupDAO;
+ @Autowired
+ protected VirAttrHandler virtAttrHandler;
+
@Override
public Pair<Long, List<PropagationStatus>> create(final GroupTO group) {
return create(group, Collections.<String>emptySet());
@@ -119,6 +124,18 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
List<PropagationTask> tasks = propagationManager.getGroupUpdateTasks(updated,
groupMod.getVirAttrsToRemove(), groupMod.getVirAttrsToUpdate(), excludedResources);
+ if (tasks.isEmpty()) {
+ // SYNCOPE-459: take care of user virtual attributes ...
+ PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
+ updated.getResult(),
+ AnyTypeKind.GROUP,
+ groupMod.getVirAttrsToRemove(),
+ groupMod.getVirAttrsToUpdate());
+ tasks.addAll(!propByResVirAttr.isEmpty()
+ ? propagationManager.getGroupUpdateTasks(updated, null, null, null)
+ : Collections.<PropagationTask>emptyList());
+ }
+
PropagationReporter propagationReporter =
ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
try {
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
index 88d3094..656bc75 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
@@ -30,6 +30,7 @@ import org.apache.syncope.common.lib.mod.StatusMod;
import org.apache.syncope.common.lib.mod.UserMod;
import org.apache.syncope.common.lib.to.PropagationStatus;
import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -42,6 +43,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
import org.apache.syncope.core.workflow.api.UserWorkflowAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -120,6 +122,7 @@ public class DefaultUserProvisioningManager implements UserProvisioningManager {
// SYNCOPE-459: take care of user virtual attributes ...
PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
updated.getResult().getKey().getKey(),
+ AnyTypeKind.USER,
userMod.getVirAttrsToRemove(),
userMod.getVirAttrsToUpdate());
tasks.addAll(!propByResVirAttr.isEmpty()
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
deleted file mode 100644
index 6c11f8a..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.java;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.mod.AttrMod;
-import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
-import org.apache.syncope.common.lib.types.MappingPurpose;
-import org.apache.syncope.common.lib.types.PropagationByResource;
-import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
-import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-import org.apache.syncope.core.persistence.api.entity.VirSchema;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-@Component
-@Transactional(rollbackFor = { Throwable.class })
-public class VirAttrHandler {
-
- private static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
-
- @Autowired
- private VirSchemaDAO virSchemaDAO;
-
- @Autowired
- private VirAttrDAO virAttrDAO;
-
- @Autowired
- private AnyObjectDAO anyObjectDAO;
-
- @Autowired
- private UserDAO userDAO;
-
- @Autowired
- private AnyUtilsFactory anyUtilsFactory;
-
- public VirSchema getVirSchema(final String virSchemaName) {
- VirSchema virtualSchema = null;
- if (StringUtils.isNotBlank(virSchemaName)) {
- virtualSchema = virSchemaDAO.find(virSchemaName);
-
- if (virtualSchema == null) {
- LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
- }
- }
-
- return virtualSchema;
- }
-
- public void updateOnResourcesIfMappingMatches(final Any<?, ?, ?> any, final AnyUtils anyUtils,
- final String schemaKey, final Set<ExternalResource> resources, final IntMappingType mappingType,
- final PropagationByResource propByRes) {
-
- for (ExternalResource resource : resources) {
- for (MappingItem mapItem : anyUtils.getMappingItems(
- resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
-
- if (schemaKey.equals(mapItem.getIntAttrName()) && mapItem.getIntMappingType() == mappingType) {
- propByRes.add(ResourceOperation.UPDATE, resource.getKey());
- }
- }
- }
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public PropagationByResource fillVirtual(final Any any,
- final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated, final AnyUtils anyUtils) {
-
- PropagationByResource propByRes = new PropagationByResource();
-
- Set<ExternalResource> externalResources = new HashSet<>();
- if (any instanceof User) {
- externalResources.addAll(userDAO.findAllResources((User) any));
- } else if (any instanceof Group) {
- externalResources.addAll(((Group) any).getResources());
- } else if (any instanceof AnyObject) {
- externalResources.addAll(anyObjectDAO.findAllResources((AnyObject) any));
- }
-
- // 1. virtual attributes to be removed
- for (String vAttrToBeRemoved : vAttrsToBeRemoved) {
- VirSchema virSchema = getVirSchema(vAttrToBeRemoved);
- if (virSchema != null) {
- VirAttr virAttr = any.getVirAttr(virSchema.getKey());
- if (virAttr == null) {
- LOG.debug("No virtual attribute found for schema {}", virSchema.getKey());
- } else {
- any.remove(virAttr);
- virAttrDAO.delete(virAttr);
- }
-
- for (ExternalResource resource : externalResources) {
- for (MappingItem mapItem : anyUtils.getMappingItems(
- resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
-
- if (virSchema.getKey().equals(mapItem.getIntAttrName())
- && mapItem.getIntMappingType() == anyUtils.virIntMappingType()) {
-
- propByRes.add(ResourceOperation.UPDATE, resource.getKey());
-
- // Using virtual attribute as ConnObjectKey must be avoided
- if (mapItem.isConnObjectKey() && virAttr != null && !virAttr.getValues().isEmpty()) {
- propByRes.addOldConnObjectKey(resource.getKey(), virAttr.getValues().get(0).toString());
- }
- }
- }
- }
- }
- }
-
- LOG.debug("Virtual attributes to be removed:\n{}", propByRes);
-
- // 2. virtual attributes to be updated
- for (AttrMod vAttrToBeUpdated : vAttrsToBeUpdated) {
- VirSchema virSchema = getVirSchema(vAttrToBeUpdated.getSchema());
- VirAttr virAttr = null;
- if (virSchema != null) {
- virAttr = any.getVirAttr(virSchema.getKey());
- if (virAttr == null) {
- virAttr = anyUtils.newVirAttr();
- virAttr.setSchema(virSchema);
- if (virAttr.getSchema() == null) {
- LOG.debug("Ignoring {} because no valid schema was found", vAttrToBeUpdated);
- } else {
- any.add(virAttr);
- }
- }
- }
-
- if (virSchema != null && virAttr != null && virAttr.getSchema() != null) {
- updateOnResourcesIfMappingMatches(any, anyUtils, virSchema.getKey(),
- externalResources, anyUtils.derIntMappingType(), propByRes);
-
- List<String> values = new ArrayList<>(virAttr.getValues());
- values.removeAll(vAttrToBeUpdated.getValuesToBeRemoved());
- values.addAll(vAttrToBeUpdated.getValuesToBeAdded());
-
- virAttr.getValues().clear();
- virAttr.getValues().addAll(values);
-
- // Owner cannot be specified before otherwise a virtual attribute remove will be invalidated.
- virAttr.setOwner(any);
- }
- }
-
- LOG.debug("Virtual attributes to be added:\n{}", propByRes);
-
- return propByRes;
- }
-
- /**
- * Add virtual attributes and specify values to be propagated.
- *
- * @param any any.
- * @param vAttrs virtual attributes to be added.
- * @param anyUtils utils
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public void fillVirtual(final Any any, final Collection<AttrTO> vAttrs, final AnyUtils anyUtils) {
- for (AttrTO attrTO : vAttrs) {
- VirAttr virAttr = any.getVirAttr(attrTO.getSchema());
- if (virAttr == null) {
- VirSchema virSchema = getVirSchema(attrTO.getSchema());
- if (virSchema != null) {
- virAttr = anyUtils.newVirAttr();
- virAttr.setSchema(virSchema);
- if (virAttr.getSchema() == null) {
- LOG.debug("Ignoring {} because no valid schema was found", attrTO);
- } else {
- virAttr.setOwner(any);
- any.add(virAttr);
- virAttr.getValues().clear();
- virAttr.getValues().addAll(attrTO.getValues());
- }
- }
- } else {
- virAttr.getValues().clear();
- virAttr.getValues().addAll(attrTO.getValues());
- }
- }
- }
-
- /**
- * SYNCOPE-459: build virtual attribute changes in case no other changes were made.
- *
- * @param key user id
- * @param vAttrsToBeRemoved virtual attributes to be removed.
- * @param vAttrsToBeUpdated virtual attributes to be updated.
- * @return operations to be performed on external resources for virtual attributes changes
- */
- public PropagationByResource fillVirtual(
- final Long key, final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
-
- return fillVirtual(
- anyObjectDAO.authFind(key),
- vAttrsToBeRemoved,
- vAttrsToBeUpdated,
- anyUtilsFactory.getInstance(AnyTypeKind.USER));
- }
-}
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
new file mode 100644
index 0000000..21626f5
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
@@ -0,0 +1,411 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java;
+
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.mod.AttrMod;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.misc.MappingUtils;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.VirAttr;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.ConnectorFactory;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.OperationOptions;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+@Transactional(rollbackFor = { Throwable.class })
+public class VirAttrHandlerImpl implements VirAttrHandler {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
+
+ @Autowired
+ private VirSchemaDAO virSchemaDAO;
+
+ @Autowired
+ private VirAttrDAO virAttrDAO;
+
+ @Autowired
+ private AnyObjectDAO anyObjectDAO;
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Autowired
+ private GroupDAO groupDAO;
+
+ @Autowired
+ private AnyUtilsFactory anyUtilsFactory;
+
+ @Autowired
+ private ConnectorFactory connFactory;
+
+ /**
+ * Virtual attribute cache.
+ */
+ @Autowired
+ private VirAttrCache virAttrCache;
+
+ @Override
+ public VirSchema getVirSchema(final String virSchemaName) {
+ VirSchema virtualSchema = null;
+ if (StringUtils.isNotBlank(virSchemaName)) {
+ virtualSchema = virSchemaDAO.find(virSchemaName);
+
+ if (virtualSchema == null) {
+ LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
+ }
+ }
+
+ return virtualSchema;
+ }
+
+ @Override
+ public void updateOnResourcesIfMappingMatches(final Any<?, ?, ?> any, final AnyUtils anyUtils,
+ final String schemaKey, final Iterable<? extends ExternalResource> resources,
+ final IntMappingType mappingType, final PropagationByResource propByRes) {
+
+ for (ExternalResource resource : resources) {
+ for (MappingItem mapItem : anyUtils.getMappingItems(
+ resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
+
+ if (schemaKey.equals(mapItem.getIntAttrName()) && mapItem.getIntMappingType() == mappingType) {
+ propByRes.add(ResourceOperation.UPDATE, resource.getKey());
+ }
+ }
+ }
+ }
+
+ private Iterable<? extends ExternalResource> getAllResources(final Any<?, ?, ?> any) {
+ return any instanceof User
+ ? userDAO.findAllResources((User) any)
+ : any instanceof AnyObject
+ ? anyObjectDAO.findAllResources((AnyObject) any)
+ : any instanceof Group
+ ? ((Group) any).getResources()
+ : Collections.<ExternalResource>emptySet();
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public PropagationByResource fillVirtual(final Any any,
+ final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
+
+ AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+
+ PropagationByResource propByRes = new PropagationByResource();
+
+ Iterable<? extends ExternalResource> externalResources = getAllResources(any);
+
+ // 1. virtual attributes to be removed
+ for (String vAttrToBeRemoved : vAttrsToBeRemoved) {
+ VirSchema virSchema = getVirSchema(vAttrToBeRemoved);
+ if (virSchema != null) {
+ VirAttr virAttr = any.getVirAttr(virSchema.getKey());
+ if (virAttr == null) {
+ LOG.debug("No virtual attribute found for schema {}", virSchema.getKey());
+ } else {
+ any.remove(virAttr);
+ virAttrDAO.delete(virAttr);
+ }
+
+ for (ExternalResource resource : externalResources) {
+ for (MappingItem mapItem : anyUtils.getMappingItems(
+ resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
+
+ if (virSchema.getKey().equals(mapItem.getIntAttrName())
+ && mapItem.getIntMappingType() == anyUtils.virIntMappingType()) {
+
+ propByRes.add(ResourceOperation.UPDATE, resource.getKey());
+
+ // Using virtual attribute as ConnObjectKey must be avoided
+ if (mapItem.isConnObjectKey() && virAttr != null && !virAttr.getValues().isEmpty()) {
+ propByRes.addOldConnObjectKey(resource.getKey(), virAttr.getValues().get(0).toString());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ LOG.debug("Virtual attributes to be removed:\n{}", propByRes);
+
+ // 2. virtual attributes to be updated
+ for (AttrMod vAttrToBeUpdated : vAttrsToBeUpdated) {
+ VirSchema virSchema = getVirSchema(vAttrToBeUpdated.getSchema());
+ if (virSchema != null) {
+ VirAttr virAttr = any.getVirAttr(virSchema.getKey());
+ if (virAttr == null) {
+ virAttr = anyUtils.newVirAttr();
+ virAttr.setOwner(any);
+ virAttr.setSchema(virSchema);
+
+ any.add(virAttr);
+ }
+
+ updateOnResourcesIfMappingMatches(any, anyUtils, virSchema.getKey(),
+ externalResources, anyUtils.derIntMappingType(), propByRes);
+
+ List<String> values = new ArrayList<>(virAttr.getValues());
+ values.removeAll(vAttrToBeUpdated.getValuesToBeRemoved());
+ values.addAll(vAttrToBeUpdated.getValuesToBeAdded());
+
+ virAttr.getValues().clear();
+ virAttr.getValues().addAll(values);
+ }
+ }
+
+ LOG.debug("Virtual attributes to be added:\n{}", propByRes);
+
+ return propByRes;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public void fillVirtual(final Any any, final Collection<AttrTO> vAttrs) {
+ AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+
+ for (AttrTO attrTO : vAttrs) {
+ VirAttr virAttr = any.getVirAttr(attrTO.getSchema());
+ if (virAttr == null) {
+ VirSchema virSchema = getVirSchema(attrTO.getSchema());
+ if (virSchema != null) {
+ virAttr = anyUtils.newVirAttr();
+ virAttr.setSchema(virSchema);
+ if (virAttr.getSchema() == null) {
+ LOG.debug("Ignoring {} because no valid schema was found", attrTO);
+ } else {
+ virAttr.setOwner(any);
+ any.add(virAttr);
+ virAttr.getValues().clear();
+ virAttr.getValues().addAll(attrTO.getValues());
+ }
+ }
+ } else {
+ virAttr.getValues().clear();
+ virAttr.getValues().addAll(attrTO.getValues());
+ }
+ }
+ }
+
+ private Any<?, ?, ?> find(final Long key, final AnyTypeKind anyTypeKind) {
+ Any<?, ?, ?> result;
+
+ switch (anyTypeKind) {
+ case USER:
+ result = userDAO.authFind(key);
+ break;
+
+ case GROUP:
+ result = groupDAO.authFind(key);
+ break;
+
+ case ANY_OBJECT:
+ default:
+ result = anyObjectDAO.authFind(key);
+ }
+
+ return result;
+ }
+
+ @Transactional
+ @Override
+ public PropagationByResource fillVirtual(
+ final Long key, final AnyTypeKind anyTypeKind,
+ final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
+
+ return fillVirtual(
+ find(key, anyTypeKind),
+ vAttrsToBeRemoved,
+ vAttrsToBeUpdated);
+ }
+
+ @Override
+ public void retrieveVirAttrValues(final Any<?, ?, ?> any) {
+ IntMappingType type = any.getType().getKind() == AnyTypeKind.USER
+ ? IntMappingType.UserVirtualSchema
+ : any.getType().getKind() == AnyTypeKind.GROUP
+ ? IntMappingType.GroupVirtualSchema
+ : IntMappingType.AnyVirtualSchema;
+
+ Map<String, ConnectorObject> resources = new HashMap<>();
+
+ // -----------------------
+ // Retrieve virtual attribute values if and only if they have not been retrieved yet
+ // -----------------------
+ for (VirAttr<?> virAttr : any.getVirAttrs()) {
+ // reset value set
+ if (virAttr.getValues().isEmpty()) {
+ retrieveVirAttrValue(any, virAttr, type, resources);
+ }
+ }
+ // -----------------------
+ }
+
+ private void retrieveVirAttrValue(
+ final Any<?, ?, ?> any,
+ final VirAttr<?> virAttr,
+ final IntMappingType type,
+ final Map<String, ConnectorObject> externalResources) {
+
+ String schemaName = virAttr.getSchema().getKey();
+ VirAttrCacheValue virAttrCacheValue = virAttrCache.get(any.getType().getKey(), any.getKey(), schemaName);
+
+ LOG.debug("Retrieve values for virtual attribute {} ({})", schemaName, type);
+
+ if (virAttrCache.isValidEntry(virAttrCacheValue)) {
+ // cached ...
+ LOG.debug("Values found in cache {}", virAttrCacheValue);
+ virAttr.getValues().clear();
+ virAttr.getValues().addAll(new ArrayList<>(virAttrCacheValue.getValues()));
+ } else {
+ // not cached ...
+ LOG.debug("Need one or more remote connections");
+
+ VirAttrCacheValue toBeCached = new VirAttrCacheValue();
+
+ AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+
+ for (ExternalResource resource : getTargetResources(virAttr, type, anyUtils, any.getType())) {
+ Provision provision = resource.getProvision(any.getType());
+ LOG.debug("Search values into {},{}", resource, provision);
+
+ try {
+ List<MappingItem> mappings = anyUtils.getMappingItems(provision, MappingPurpose.BOTH);
+
+ ConnectorObject connectorObject;
+ if (externalResources.containsKey(resource.getKey())) {
+ connectorObject = externalResources.get(resource.getKey());
+ } else {
+ LOG.debug("Perform connection to {}", resource.getKey());
+ String connObjectKey = anyUtils.getConnObjectKeyItem(provision) == null
+ ? null
+ : MappingUtils.getConnObjectKeyValue(any, provision);
+
+ if (StringUtils.isBlank(connObjectKey)) {
+ throw new IllegalArgumentException("No ConnObjectKey found for " + resource.getKey());
+ }
+
+ Connector connector = connFactory.getConnector(resource);
+
+ OperationOptions oo =
+ connector.getOperationOptions(MappingUtils.getMatchingMappingItems(mappings, type));
+
+ connectorObject =
+ connector.getObject(provision.getObjectClass(), new Uid(connObjectKey), oo);
+ externalResources.put(resource.getKey(), connectorObject);
+ }
+
+ if (connectorObject != null) {
+ // ask for searched virtual attribute value
+ Collection<MappingItem> virAttrMappings =
+ MappingUtils.getMatchingMappingItems(mappings, schemaName, type);
+
+ // the same virtual attribute could be mapped with one or more external attribute
+ for (MappingItem mapping : virAttrMappings) {
+ Attribute attribute = connectorObject.getAttributeByName(mapping.getExtAttrName());
+
+ if (attribute != null && attribute.getValue() != null) {
+ for (Object obj : attribute.getValue()) {
+ if (obj != null) {
+ virAttr.getValues().add(obj.toString());
+ }
+ }
+ }
+ }
+
+ toBeCached.setResourceValues(resource.getKey(), new HashSet<>(virAttr.getValues()));
+
+ LOG.debug("Retrieved values {}", virAttr.getValues());
+ }
+ } catch (Exception e) {
+ LOG.error("Error reading connector object from {}", resource.getKey(), e);
+
+ if (virAttrCacheValue != null) {
+ toBeCached.forceExpiring();
+ LOG.debug("Search for a cached value (even expired!) ...");
+ final Set<String> cachedValues = virAttrCacheValue.getValues(resource.getKey());
+ if (cachedValues != null) {
+ LOG.debug("Use cached value {}", cachedValues);
+ virAttr.getValues().addAll(cachedValues);
+ toBeCached.setResourceValues(resource.getKey(), new HashSet<>(cachedValues));
+ }
+ }
+ }
+ }
+
+ virAttrCache.put(any.getType().getKey(), any.getKey(), schemaName, toBeCached);
+ }
+ }
+
+ private Collection<ExternalResource> getTargetResources(
+ final VirAttr<?> attr, final IntMappingType type, final AnyUtils anyUtils, final AnyType anyType) {
+
+ return CollectionUtils.select(getAllResources(attr.getOwner()), new Predicate<ExternalResource>() {
+
+ @Override
+ public boolean evaluate(final ExternalResource resource) {
+ return resource.getProvision(anyType) != null
+ && !MappingUtils.getMatchingMappingItems(
+ anyUtils.getMappingItems(resource.getProvision(anyType), MappingPurpose.BOTH),
+ attr.getSchema().getKey(), type).isEmpty();
+ }
+ });
+ }
+}