You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2012/03/28 17:29:48 UTC

svn commit: r1306418 - in /incubator/syncope/trunk: client/src/main/java/org/syncope/client/to/ client/src/main/java/org/syncope/types/ console/src/main/java/org/syncope/console/pages/ console/src/main/java/org/syncope/console/pages/panels/ console/src...

Author: fmartelli
Date: Wed Mar 28 15:29:47 2012
New Revision: 1306418

URL: http://svn.apache.org/viewvc?rev=1306418&view=rev
Log:
SYNCOPE-41 #comment provided fields to store email attribute type/schema

Modified:
    incubator/syncope/trunk/client/src/main/java/org/syncope/client/to/NotificationTO.java
    incubator/syncope/trunk/client/src/main/java/org/syncope/types/IntMappingType.java
    incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/NotificationModalPage.java
    incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/panels/ResourceMappingPanel.java
    incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.html
    incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.properties
    incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage_it.properties
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/notification/NotificationManager.java
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/persistence/beans/Notification.java
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/NotificationDataBinder.java
    incubator/syncope/trunk/core/src/main/java/org/syncope/core/util/SchemaMappingUtil.java
    incubator/syncope/trunk/core/src/main/resources/content.xml
    incubator/syncope/trunk/core/src/test/java/org/syncope/core/persistence/dao/NotificationTest.java
    incubator/syncope/trunk/core/src/test/java/org/syncope/core/rest/NotificationTestITCase.java
    incubator/syncope/trunk/core/src/test/resources/content.xml

Modified: incubator/syncope/trunk/client/src/main/java/org/syncope/client/to/NotificationTO.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/client/src/main/java/org/syncope/client/to/NotificationTO.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/client/src/main/java/org/syncope/client/to/NotificationTO.java (original)
+++ incubator/syncope/trunk/client/src/main/java/org/syncope/client/to/NotificationTO.java Wed Mar 28 15:29:47 2012
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.syncope.client.AbstractBaseBean;
 import org.syncope.client.search.NodeCond;
+import org.syncope.types.IntMappingType;
 import org.syncope.types.TraceLevel;
 
 public class NotificationTO extends AbstractBaseBean {
@@ -36,6 +37,10 @@ public class NotificationTO extends Abst
 
     private NodeCond recipients;
 
+    private IntMappingType recipientAttrType;
+
+    private String recipientAttrName;
+
     private boolean selfAsRecipient;
 
     private String sender;
@@ -90,6 +95,22 @@ public class NotificationTO extends Abst
         this.recipients = recipients;
     }
 
+    public String getRecipientAttrName() {
+        return recipientAttrName;
+    }
+
+    public void setRecipientAttrName(String recipientAttrName) {
+        this.recipientAttrName = recipientAttrName;
+    }
+
+    public IntMappingType getRecipientAttrType() {
+        return recipientAttrType;
+    }
+
+    public void setRecipientAttrType(IntMappingType recipientAttrType) {
+        this.recipientAttrType = recipientAttrType;
+    }
+
     public boolean isSelfAsRecipient() {
         return selfAsRecipient;
     }

Modified: incubator/syncope/trunk/client/src/main/java/org/syncope/types/IntMappingType.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/client/src/main/java/org/syncope/types/IntMappingType.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/client/src/main/java/org/syncope/types/IntMappingType.java (original)
+++ incubator/syncope/trunk/client/src/main/java/org/syncope/types/IntMappingType.java Wed Mar 28 15:29:47 2012
@@ -19,6 +19,8 @@
 package org.syncope.types;
 
 import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * Internal attribute mapping type.
@@ -62,17 +64,45 @@ public enum IntMappingType {
      * Get attribute types for a certain attributable type.
      *
      * @param attributableType attributable type
+     * @param toBeFiltered types to be filtered from the result.
      * @return set of attribute types.
      */
-    public static EnumSet<?> getAttributeTypes(final AttributableType attributableType) {
+    public static Set<IntMappingType> getAttributeTypes(
+            final AttributableType attributableType, final Set<IntMappingType> toBeFiltered) {
+
+        final Set<IntMappingType> res = getAttributeTypes(attributableType);
+        res.removeAll(toBeFiltered);
+
+        return res;
+    }
+
+    /**
+     * Get attribute types for a certain attributable type.
+     *
+     * @param attributableType attributable type
+     * @return set of attribute types.
+     */
+    public static Set<IntMappingType> getAttributeTypes(final AttributableType attributableType) {
+        final EnumSet<?> enumset;
+
         switch (attributableType) {
             case ROLE:
-                return EnumSet.allOf(RoleMappingType.class);
+                enumset = EnumSet.allOf(RoleMappingType.class);
+                break;
             case MEMBERSHIP:
-                return EnumSet.allOf(MembershipMappingType.class);
+                enumset = EnumSet.allOf(MembershipMappingType.class);
+                break;
             default:
-                return EnumSet.allOf(UserMappingType.class);
+                enumset = EnumSet.allOf(UserMappingType.class);
+        }
+
+        final Set<IntMappingType> res = new HashSet<IntMappingType>();
+
+        for (Object obj : enumset) {
+            res.add(IntMappingType.valueOf(obj.toString()));
         }
+
+        return res;
     }
 
     /**
@@ -104,7 +134,6 @@ public enum IntMappingType {
         SyncopeUserId,
         Password,
         Username;
-
     }
 
     /**
@@ -115,7 +144,6 @@ public enum IntMappingType {
         RoleSchema,
         RoleDerivedSchema,
         RoleVirtualSchema;
-
     }
 
     /**
@@ -126,6 +154,5 @@ public enum IntMappingType {
         MembershipSchema,
         MembershipDerivedSchema,
         MembershipVirtualSchema;
-
     }
 }

Modified: incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/NotificationModalPage.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/NotificationModalPage.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/NotificationModalPage.java (original)
+++ incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/NotificationModalPage.java Wed Mar 28 15:29:47 2012
@@ -18,9 +18,15 @@
  */
 package org.syncope.console.pages;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
@@ -29,6 +35,7 @@ import org.apache.wicket.markup.html.for
 import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.util.ListModel;
 import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.apache.wicket.validation.validator.EmailAddressValidator;
@@ -36,10 +43,13 @@ import org.syncope.client.to.Notificatio
 import org.syncope.client.validation.SyncopeClientCompositeErrorException;
 import org.syncope.console.pages.panels.UserSearchPanel;
 import org.syncope.console.rest.NotificationRestClient;
+import org.syncope.console.rest.SchemaRestClient;
 import org.syncope.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import org.syncope.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
 import org.syncope.console.wicket.markup.html.form.AjaxPalettePanel;
 import org.syncope.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.syncope.types.AttributableType;
+import org.syncope.types.IntMappingType;
 import org.syncope.types.TraceLevel;
 
 class NotificationModalPage extends BaseModalPage {
@@ -49,6 +59,14 @@ class NotificationModalPage extends Base
     @SpringBean
     private NotificationRestClient restClient;
 
+    @SpringBean
+    private SchemaRestClient schemaRestClient;
+
+    /**
+     * OnChange event name.
+     */
+    private static String onchange = "onchange";
+
     public NotificationModalPage(final PageReference callPageRef, final ModalWindow window,
             final NotificationTO notificationTO, final boolean createFlag) {
 
@@ -81,6 +99,39 @@ class NotificationModalPage extends Base
         final UserSearchPanel about = new UserSearchPanel("about", notificationTO.getAbout());
         form.add(about);
 
+        final AjaxDropDownChoicePanel<IntMappingType> recipientAttrType = new AjaxDropDownChoicePanel<IntMappingType>(
+                "recipientAttrType",
+                new ResourceModel("recipientAttrType", "recipientAttrType").getObject(),
+                new PropertyModel<IntMappingType>(notificationTO, "recipientAttrType"));
+
+        final Set<IntMappingType> toBeFiltered = new HashSet<IntMappingType>();
+        toBeFiltered.add(IntMappingType.SyncopeUserId);
+        toBeFiltered.add(IntMappingType.Password);
+
+        recipientAttrType.setChoices(new ArrayList<IntMappingType>(
+                (Set<IntMappingType>) IntMappingType.getAttributeTypes(AttributableType.USER, toBeFiltered)));
+
+        recipientAttrType.setRequired(true);
+        form.add(recipientAttrType);
+
+        final AjaxDropDownChoicePanel<String> recipientAttrName = new AjaxDropDownChoicePanel<String>(
+                "recipientAttrName",
+                new ResourceModel("recipientAttrName", "recipientAttrName").getObject(),
+                new PropertyModel(notificationTO, "recipientAttrName"));
+
+        recipientAttrName.setChoices(getSchemaNames(notificationTO.getRecipientAttrType()));
+        recipientAttrName.setRequired(true);
+        form.add(recipientAttrName);
+
+        recipientAttrType.getField().add(new AjaxFormComponentUpdatingBehavior(onchange) {
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                recipientAttrName.setChoices(getSchemaNames(notificationTO.getRecipientAttrType()));
+                target.add(recipientAttrName);
+            }
+        });
+
         final AjaxPalettePanel events = new AjaxPalettePanel("events", new PropertyModel(notificationTO, "events"),
                 new ListModel<String>(restClient.getEvents()));
         form.add(events);
@@ -136,4 +187,23 @@ class NotificationModalPage extends Base
 
         add(form);
     }
+
+    private List<String> getSchemaNames(final IntMappingType type) {
+        if (type == null) {
+            return Collections.EMPTY_LIST;
+        }
+
+        switch (type) {
+            case UserSchema:
+                return schemaRestClient.getSchemaNames(AttributableType.USER);
+            case UserDerivedSchema:
+                return schemaRestClient.getDerivedSchemaNames(AttributableType.USER);
+            case UserVirtualSchema:
+                return schemaRestClient.getVirtualSchemaNames(AttributableType.USER);
+            case Username:
+                return Collections.singletonList("Username");
+            default:
+                return Collections.EMPTY_LIST;
+        }
+    }
 }

Modified: incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/panels/ResourceMappingPanel.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/panels/ResourceMappingPanel.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/panels/ResourceMappingPanel.java (original)
+++ incubator/syncope/trunk/console/src/main/java/org/syncope/console/pages/panels/ResourceMappingPanel.java Wed Mar 28 15:29:47 2012
@@ -21,7 +21,6 @@ package org.syncope.console.pages.panels
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -287,7 +286,7 @@ public class ResourceMappingPanel extend
                         "mandatoryCondition", "mandatoryCondition").getObject(), new PropertyModel(mappingTO,
                         "mandatoryCondition"));
 
-                mandatory.setChoices(Arrays.asList(new String[] { "true", "false" }));
+                mandatory.setChoices(Arrays.asList(new String[]{"true", "false"}));
 
                 mandatory.setStyleShet(shortFieldStyle);
 
@@ -546,11 +545,7 @@ public class ResourceMappingPanel extend
         final List<IntMappingType> res = new ArrayList<IntMappingType>();
 
         if (entity != null) {
-            final EnumSet types = IntMappingType.getAttributeTypes(AttributableType.valueOf(entity.toString()));
-
-            for (Object type : types) {
-                res.add(IntMappingType.valueOf(type.toString()));
-            }
+            res.addAll(IntMappingType.getAttributeTypes(AttributableType.valueOf(entity.toString())));
         }
 
         return res;

Modified: incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.html
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.html?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.html (original)
+++ incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.html Wed Mar 28 15:29:47 2012
@@ -13,90 +13,108 @@
  under the License.
 -->
 <wicket:extend>
-    <div style="margin:10px">
-        <p class="ui-widget ui-corner-all ui-widget-header"><wicket:message key="title"/></p>
-        <form wicket:id="form">
-            <div id="tabs">
-                <ul>
-                    <li  class="tabs-selected"><a href="#notification"><span><wicket:message key="notification"/></span></a></li>
-                    <li><a href="#about"><span><wicket:message key="about"/></span></a></li>
-                    <li><a href="#events"><span><wicket:message key="events"/></span></a></li>
-                    <li><a href="#recipients"><span><wicket:message key="recipients"/></span></a></li>
-                </ul>
-
-                <div id="notification">
-                    <div id="formtable">
-                        <div class="tablerow">
-                            <div class="tablecolumn_label medium_fixedsize">
-                                <label for="sender"><wicket:message key="sender"/></label>
-                            </div>
-                            <div class="tablecolumn_field medium_dynamicsize">
-                                <span wicket:id="sender">[sender]</span>
-                            </div>
-                        </div>
-
-                        <div class="tablerow">
-                            <div class="tablecolumn_label medium_fixedsize">
-                                <label for="subject"><wicket:message key="subject"/></label>
-                            </div>
-                            <div class="tablecolumn_field medium_dynamicsize">
-                                <span wicket:id="subject">[subject]</span>
-                            </div>
-                        </div>
-
-                        <div class="tablerow">
-                            <div class="tablecolumn_label medium_fixedsize">
-                                <label for="template"><wicket:message key="template"/></label>
-                            </div>
-                            <div class="tablecolumn_field medium_dynamicsize">
-                                <span wicket:id="template">[template]</span>
-                            </div>
-                        </div>
-
-                        <div class="tablerow">
-                            <div class="tablecolumn_label medium_fixedsize">
-                                <label for="traceLevel"><wicket:message key="traceLevel"/></label>
-                            </div>
-                            <div class="tablecolumn_field medium_dynamicsize">
-                                <span wicket:id="traceLevel">[traceLevel]</span>
-                            </div>
-                        </div>
-                    </div>
-
-                    <script type="text/javascript">
-                        $(function() {
-                            $('div#notification div#formtable div.tablerow:even').addClass("alt");
-                        });
-                    </script>
-                </div>
-
-                <div id="about">
-                    <span wicket:id="about"/>
-                </div>
-
-                <div id="events">
-                    <span wicket:id="events"/>
-                </div>
-
-                <div id="recipients">
-                    <span wicket:id="recipients"/>
-
-                    <div class="tablerow">
-                        <div class="tablecolumn_label medium_fixedsize">
-                            <label for="selfAsRecipient"><wicket:message key="selfAsRecipient"/></label>
-                        </div>
-                        <div class="tablecolumn_field medium_dynamicsize">
-                            <span wicket:id="selfAsRecipient">[selfAsRecipient]</span>
-                        </div>
-                    </div>
-                </div>
-            </div>
-
-            <div style="margin: 20px 10px 0">
-                <input type="submit"
-                       class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
-                       wicket:id="apply"/>
+  <div style="margin:10px">
+    <p class="ui-widget ui-corner-all ui-widget-header"><wicket:message key="title"/></p>
+    <form wicket:id="form">
+      <div id="tabs">
+        <ul>
+          <li  class="tabs-selected"><a href="#notification"><span><wicket:message key="notification"/></span></a></li>
+          <li><a href="#about"><span><wicket:message key="about"/></span></a></li>
+          <li><a href="#events"><span><wicket:message key="events"/></span></a></li>
+          <li><a href="#recipients"><span><wicket:message key="recipients"/></span></a></li>
+        </ul>
+
+        <div id="notification">
+          <div id="formtable">
+            <div class="tablerow">
+              <div class="tablecolumn_label medium_fixedsize">
+                <label for="sender"><wicket:message key="sender"/></label>
+              </div>
+              <div class="tablecolumn_field medium_dynamicsize">
+                <span wicket:id="sender">[sender]</span>
+              </div>
             </div>
-        </form>
-    </div>
+
+            <div class="tablerow">
+              <div class="tablecolumn_label medium_fixedsize">
+                <label for="subject"><wicket:message key="subject"/></label>
+              </div>
+              <div class="tablecolumn_field medium_dynamicsize">
+                <span wicket:id="subject">[subject]</span>
+              </div>
+            </div>
+
+            <div class="tablerow">
+              <div class="tablecolumn_label medium_fixedsize">
+                <label for="recipientAttrType"><wicket:message key="recipientAttrType"/></label>
+              </div>
+              <div class="tablecolumn_field medium_dynamicsize">
+                <span wicket:id="recipientAttrType">[recipientAttrType]</span>
+              </div>
+            </div>
+
+            <div class="tablerow">
+              <div class="tablecolumn_label medium_fixedsize">
+                <label for="recipientAttrName"><wicket:message key="recipientAttrName"/></label>
+              </div>
+              <div class="tablecolumn_field medium_dynamicsize">
+                <span wicket:id="recipientAttrName">[recipientAttrName]</span>
+              </div>
+            </div>
+
+            <div class="tablerow">
+              <div class="tablecolumn_label medium_fixedsize">
+                <label for="template"><wicket:message key="template"/></label>
+              </div>
+              <div class="tablecolumn_field medium_dynamicsize">
+                <span wicket:id="template">[template]</span>
+              </div>
+            </div>
+
+            <div class="tablerow">
+              <div class="tablecolumn_label medium_fixedsize">
+                <label for="traceLevel"><wicket:message key="traceLevel"/></label>
+              </div>
+              <div class="tablecolumn_field medium_dynamicsize">
+                <span wicket:id="traceLevel">[traceLevel]</span>
+              </div>
+            </div>
+          </div>
+
+          <script type="text/javascript">
+            $(function() {
+              $('div#notification div#formtable div.tablerow:even').addClass("alt");
+            });
+          </script>
+        </div>
+
+        <div id="about">
+          <span wicket:id="about"/>
+        </div>
+
+        <div id="events">
+          <span wicket:id="events"/>
+        </div>
+
+        <div id="recipients">
+          <span wicket:id="recipients"/>
+
+          <div class="tablerow">
+            <div class="tablecolumn_label medium_fixedsize">
+              <label for="selfAsRecipient"><wicket:message key="selfAsRecipient"/></label>
+            </div>
+            <div class="tablecolumn_field medium_dynamicsize">
+              <span wicket:id="selfAsRecipient">[selfAsRecipient]</span>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div style="margin: 20px 10px 0">
+        <input type="submit"
+               class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
+               wicket:id="apply"/>
+      </div>
+    </form>
+  </div>
 </wicket:extend>
\ No newline at end of file

Modified: incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.properties
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.properties?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.properties (original)
+++ incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage.properties Wed Mar 28 15:29:47 2012
@@ -25,3 +25,5 @@ about=About
 events=Events
 recipients=Recipients
 selfAsRecipient=Include users matching About
+recipientAttrType=Recipients e-mail attribute type
+recipientAttrName=Recipients e-mail attribute schema

Modified: incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage_it.properties
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage_it.properties?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage_it.properties (original)
+++ incubator/syncope/trunk/console/src/main/resources/org/syncope/console/pages/NotificationModalPage_it.properties Wed Mar 28 15:29:47 2012
@@ -25,3 +25,5 @@ about=Soggetti
 events=Eventi
 recipients=Destinatari
 selfAsRecipient=Including i soggetti
+recipientAttrType=Tipo attributo e-mail destinatari
+recipientAttrName=Shcema attributo e-mail destinatari

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/notification/NotificationManager.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/notification/NotificationManager.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/notification/NotificationManager.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/notification/NotificationManager.java Wed Mar 28 15:29:47 2012
@@ -18,6 +18,7 @@
  */
 package org.syncope.core.notification;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -36,20 +37,25 @@ import org.syncope.core.persistence.bean
 import org.syncope.core.persistence.beans.NotificationTask;
 import org.syncope.core.persistence.beans.TaskExec;
 import org.syncope.core.persistence.beans.user.SyncopeUser;
+import org.syncope.core.persistence.beans.user.UAttr;
+import org.syncope.core.persistence.beans.user.UDerAttr;
+import org.syncope.core.persistence.beans.user.UVirAttr;
 import org.syncope.core.persistence.dao.ConfDAO;
 import org.syncope.core.persistence.dao.NotificationDAO;
 import org.syncope.core.persistence.dao.TaskDAO;
 import org.syncope.core.persistence.dao.UserDAO;
 import org.syncope.core.persistence.dao.UserSearchDAO;
 import org.syncope.core.scheduling.NotificationJob;
+import org.syncope.core.util.ConnObjectUtil;
 import org.syncope.core.workflow.WorkflowResult;
+import org.syncope.types.IntMappingType;
 
 /**
  * Create notification tasks that will be executed by NotificationJob.
  *
  * @see NotificationTask
  */
-@Transactional(rollbackFor = { Throwable.class })
+@Transactional(rollbackFor = {Throwable.class})
 public class NotificationManager {
 
     /**
@@ -96,6 +102,8 @@ public class NotificationManager {
     @Autowired
     private NotificationJob notificationJob;
 
+    @Autowired
+    private ConnObjectUtil connObjectUtil;
     /**
      * Create a notification task.
      *
@@ -104,29 +112,38 @@ public class NotificationManager {
      * @param emailSchema name of user schema containing e-mail address
      * @return notification task, fully populated
      */
-    private NotificationTask getNotificationTask(final Notification notification, final SyncopeUser user,
-            final String emailSchema) {
+    private NotificationTask getNotificationTask(final Notification notification, final SyncopeUser user) {
 
-        Set<String> recipients = new HashSet<String>();
-        for (SyncopeUser recipient : searchDAO.search(notification.getRecipients())) {
+        connObjectUtil.retrieveVirAttrValues(user);
+        
+        final IntMappingType recipientAttrType = notification.getRecipientAttrType();
+        final String recipientAttrName = notification.getRecipientAttrName();
+
+        final List<SyncopeUser> recipients = new ArrayList<SyncopeUser>();
+        recipients.addAll(searchDAO.search(notification.getRecipients()));
 
-            if (recipient.getAttribute(emailSchema) == null) {
-                LOG.error("{} cannot be notified no {} attribute present", recipient, emailSchema);
-            } else {
-                recipients.add(recipient.getAttribute(emailSchema).getValuesAsStrings().get(0));
-            }
-        }
         if (notification.isSelfAsRecipient()) {
-            if (user.getAttribute(emailSchema) == null) {
-                LOG.error("{} cannot be notified no {} attribute present", user, emailSchema);
+            recipients.add(user);
+        }
+
+        Set<String> recipientEmails = new HashSet<String>();
+
+        for (SyncopeUser recipient : recipients) {
+            
+            connObjectUtil.retrieveVirAttrValues(recipient);
+
+            String email = getRecipientEmail(recipientAttrType, recipientAttrName, user);
+
+            if (email == null) {
+                LOG.error("{} cannot be notified. No {} attribute present", recipient, recipientAttrName);
             } else {
-                recipients.add(user.getAttribute(emailSchema).getValuesAsStrings().get(0));
+                recipientEmails.add(email);
             }
         }
 
         NotificationTask task = new NotificationTask();
         task.setTraceLevel(notification.getTraceLevel());
-        task.setRecipients(recipients);
+        task.setRecipients(recipientEmails);
         task.setSender(notification.getSender());
         task.setSubject(notification.getSubject());
 
@@ -136,8 +153,8 @@ public class NotificationManager {
             model.put(attr.getSchema().getName(), values.isEmpty()
                     ? ""
                     : (values.size() == 1
-                            ? values.iterator().next()
-                            : values));
+                    ? values.iterator().next()
+                    : values));
         }
 
         String htmlBody;
@@ -165,15 +182,14 @@ public class NotificationManager {
      * @param wfResult workflow result
      * @throws NotFoundException if user contained in the workflow result cannot be found
      */
-    public void createTasks(final WorkflowResult<Long> wfResult) throws NotFoundException {
+    public void createTasks(final WorkflowResult<Long> wfResult)
+            throws NotFoundException {
 
         SyncopeUser user = userDAO.find(wfResult.getResult());
         if (user == null) {
             throw new NotFoundException("User " + wfResult.getResult());
         }
 
-        final String emailSchema = confDAO.find("email.schema", "email").getValue();
-
         for (Notification notification : notificationDAO.findAll()) {
             if (searchDAO.matches(user, notification.getAbout())) {
                 Set<String> events = new HashSet<String>(notification.getEvents());
@@ -181,7 +197,7 @@ public class NotificationManager {
 
                 if (!events.isEmpty()) {
                     LOG.debug("Creating notification task for events {} about {}", events, user);
-                    taskDAO.save(getNotificationTask(notification, user, emailSchema));
+                    taskDAO.save(getNotificationTask(notification, user));
                 } else {
                     LOG.debug("No events found about {}", user);
                 }
@@ -192,4 +208,32 @@ public class NotificationManager {
     public TaskExec execute(final NotificationTask task) {
         return notificationJob.executeSingle(task);
     }
+
+    private String getRecipientEmail(
+            final IntMappingType recipientAttrType, final String recipientAttrName, final SyncopeUser user) {
+
+        final String email;
+
+        switch (recipientAttrType) {
+            case Username:
+                email = user.getUsername();
+                break;
+            case UserSchema:
+                UAttr attr = user.getAttribute(recipientAttrName);
+                email = attr == null || attr.getValuesAsStrings().isEmpty() ? null : attr.getValuesAsStrings().get(0);
+                break;
+            case UserVirtualSchema:
+                UVirAttr virAttr = user.getVirtualAttribute(recipientAttrName);
+                email = virAttr == null || virAttr.getValues().isEmpty() ? null : virAttr.getValues().get(0);
+                break;
+            case UserDerivedSchema:
+                UDerAttr derAttr = user.getDerivedAttribute(recipientAttrName);
+                email = derAttr == null ? null : derAttr.getValue(user.getAttributes());
+                break;
+            default:
+                email = null;
+        }
+
+        return email;
+    }
 }

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/persistence/beans/Notification.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/persistence/beans/Notification.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/persistence/beans/Notification.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/persistence/beans/Notification.java Wed Mar 28 15:29:47 2012
@@ -37,6 +37,7 @@ import javax.validation.constraints.NotN
 import org.syncope.client.search.NodeCond;
 import org.syncope.core.persistence.validation.entity.NotificationCheck;
 import org.syncope.client.util.XMLSerializer;
+import org.syncope.types.IntMappingType;
 import org.syncope.types.TraceLevel;
 
 @NotificationCheck
@@ -61,6 +62,13 @@ public class Notification extends Abstra
     @Lob
     private String xmlRecipients;
 
+    @NotNull
+    @Enumerated(EnumType.STRING)
+    private IntMappingType recipientAttrType;
+
+    @NotNull
+    private String recipientAttrName;
+
     @Column(nullable = false)
     @Basic
     @Min(0)
@@ -76,8 +84,8 @@ public class Notification extends Abstra
     @NotNull
     private String template;
 
-    @Enumerated(EnumType.STRING)
     @NotNull
+    @Enumerated(EnumType.STRING)
     private TraceLevel traceLevel;
 
     public Notification() {
@@ -91,7 +99,7 @@ public class Notification extends Abstra
     }
 
     public NodeCond getAbout() {
-        NodeCond result = XMLSerializer.<NodeCond> deserialize(xmlAbout);
+        NodeCond result = XMLSerializer.<NodeCond>deserialize(xmlAbout);
         if (result == null) {
             result = new NodeCond();
         }
@@ -107,7 +115,7 @@ public class Notification extends Abstra
     }
 
     public NodeCond getRecipients() {
-        NodeCond result = XMLSerializer.<NodeCond> deserialize(xmlRecipients);
+        NodeCond result = XMLSerializer.<NodeCond>deserialize(xmlRecipients);
         if (result == null) {
             result = new NodeCond();
         }
@@ -122,6 +130,22 @@ public class Notification extends Abstra
         xmlRecipients = XMLSerializer.serialize(recipients);
     }
 
+    public String getRecipientAttrName() {
+        return recipientAttrName;
+    }
+
+    public void setRecipientAttrName(String recipientAttrName) {
+        this.recipientAttrName = recipientAttrName;
+    }
+
+    public IntMappingType getRecipientAttrType() {
+        return recipientAttrType;
+    }
+
+    public void setRecipientAttrType(IntMappingType recipientAttrType) {
+        this.recipientAttrType = recipientAttrType;
+    }
+
     public List<String> getEvents() {
         return events;
     }

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/NotificationDataBinder.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/NotificationDataBinder.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/NotificationDataBinder.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/rest/data/NotificationDataBinder.java Wed Mar 28 15:29:47 2012
@@ -26,7 +26,7 @@ import org.syncope.core.persistence.bean
 @Component
 public class NotificationDataBinder {
 
-    private static final String[] IGNORE_PROPERTIES = { "id", "about", "recipients" };
+    private static final String[] IGNORE_PROPERTIES = {"id", "about", "recipients"};
 
     public NotificationTO getNotificationTO(final Notification notification) {
         NotificationTO result = new NotificationTO();

Modified: incubator/syncope/trunk/core/src/main/java/org/syncope/core/util/SchemaMappingUtil.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/syncope/core/util/SchemaMappingUtil.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/syncope/core/util/SchemaMappingUtil.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/syncope/core/util/SchemaMappingUtil.java Wed Mar 28 15:29:47 2012
@@ -148,8 +148,8 @@ public class SchemaMappingUtil {
             case UserSchema:
             case RoleSchema:
             case MembershipSchema:
-                schema = schemaDAO.find(mapping.getIntAttrName(), SchemaMappingUtil.getIntMappingTypeClass(mapping
-                        .getIntMappingType()));
+                schema = schemaDAO.find(mapping.getIntAttrName(), SchemaMappingUtil.getIntMappingTypeClass(mapping.
+                        getIntMappingType()));
 
                 for (AbstractAttributable attributable : attributables) {
                     final UAttr attr = attributable.getAttribute(mapping.getIntAttrName());
@@ -161,8 +161,8 @@ public class SchemaMappingUtil {
                     }
 
                     LOG.debug("Retrieved attribute {}" + "\n* IntAttrName {}" + "\n* IntMappingType {}"
-                            + "\n* Attribute values {}", new Object[] { attr, mapping.getIntAttrName(),
-                            mapping.getIntMappingType(), values });
+                            + "\n* Attribute values {}", new Object[]{attr, mapping.getIntAttrName(),
+                                mapping.getIntMappingType(), values});
                 }
 
                 break;
@@ -183,8 +183,8 @@ public class SchemaMappingUtil {
                     }
 
                     LOG.debug("Retrieved virtual attribute {}" + "\n* IntAttrName {}" + "\n* IntMappingType {}"
-                            + "\n* Attribute values {}", new Object[] { virAttr, mapping.getIntAttrName(),
-                            mapping.getIntMappingType(), values });
+                            + "\n* Attribute values {}", new Object[]{virAttr, mapping.getIntAttrName(),
+                                mapping.getIntMappingType(), values});
                 }
                 break;
 
@@ -201,8 +201,8 @@ public class SchemaMappingUtil {
                     }
 
                     LOG.debug("Retrieved attribute {}" + "\n* IntAttrName {}" + "\n* IntMappingType {}"
-                            + "\n* Attribute values {}", new Object[] { derAttr, mapping.getIntAttrName(),
-                            mapping.getIntMappingType(), values });
+                            + "\n* Attribute values {}", new Object[]{derAttr, mapping.getIntAttrName(),
+                                mapping.getIntMappingType(), values});
                 }
                 break;
 
@@ -240,12 +240,13 @@ public class SchemaMappingUtil {
         return new DefaultMapEntry(schema, values);
     }
 
-    public static List<String> getIntValueAsStrings(final AbstractAttributable attributable, final SchemaMapping mapping) {
+    public static List<String> getIntValueAsStrings(
+            final AbstractAttributable attributable, final SchemaMapping mapping) {
         return getIntValueAsStrings(attributable, mapping, null);
     }
 
-    public static List<String> getIntValueAsStrings(final AbstractAttributable attributable,
-            final SchemaMapping mapping, String clearPassword) {
+    public static List<String> getIntValueAsStrings(
+            final AbstractAttributable attributable, final SchemaMapping mapping, String clearPassword) {
 
         List<String> value = new ArrayList<String>();
 

Modified: incubator/syncope/trunk/core/src/main/resources/content.xml
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/resources/content.xml?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/resources/content.xml (original)
+++ incubator/syncope/trunk/core/src/main/resources/content.xml Wed Mar 28 15:29:47 2012
@@ -23,7 +23,6 @@ under the License.
   <SyncopeConf confKey="token.expireTime" confValue="60"/>
   <SyncopeConf confKey="smtp.host" confValue="smtp.ngi.it"/>
   <SyncopeConf confKey="smtp.port" confValue="25"/>
-  <SyncopeConf confKey="email.schema" confValue="email"/>
   <SyncopeConf confKey="connid.bundles.directory" confValue="${bundles.directory}"/>
   <SyncopeConf confKey="password.cipher.algorithm" confValue="MD5"/>
   <SyncopeConf confKey="createRequest.allowed" confValue="false"/>

Modified: incubator/syncope/trunk/core/src/test/java/org/syncope/core/persistence/dao/NotificationTest.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/java/org/syncope/core/persistence/dao/NotificationTest.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/java/org/syncope/core/persistence/dao/NotificationTest.java (original)
+++ incubator/syncope/trunk/core/src/test/java/org/syncope/core/persistence/dao/NotificationTest.java Wed Mar 28 15:29:47 2012
@@ -33,6 +33,7 @@ import org.syncope.core.AbstractTest;
 import org.syncope.core.persistence.beans.Notification;
 import org.syncope.core.persistence.validation.entity.InvalidEntityException;
 import org.syncope.types.EntityViolationType;
+import org.syncope.types.IntMappingType;
 
 @Transactional
 public class NotificationTest extends AbstractTest {
@@ -70,8 +71,8 @@ public class NotificationTest extends Ab
         AttributeCond fullnameLeafCond2 = new AttributeCond(AttributeCond.Type.LIKE);
         fullnameLeafCond2.setSchema("fullname");
         fullnameLeafCond2.setExpression("%i%");
-        NodeCond about = NodeCond.getAndCond(NodeCond.getLeafCond(fullnameLeafCond1), NodeCond
-                .getLeafCond(fullnameLeafCond2));
+        NodeCond about = NodeCond.getAndCond(NodeCond.getLeafCond(fullnameLeafCond1), NodeCond.getLeafCond(
+                fullnameLeafCond2));
 
         notification.setAbout(about);
 
@@ -81,6 +82,9 @@ public class NotificationTest extends Ab
 
         notification.setRecipients(recipients);
 
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserSchema);
+
         notification.setSender("syncope@syncope-idm.org");
         notification.setSubject("Test notification");
         notification.setTemplate("test");
@@ -104,6 +108,9 @@ public class NotificationTest extends Ab
 
         notification.setRecipients(recipients);
 
+        notification.setRecipientAttrName("email");
+        notification.setRecipientAttrType(IntMappingType.UserSchema);
+
         notification.setSender("syncope@syncope-idm.org");
         notification.setSubject("Test notification");
         notification.setTemplate("test");

Modified: incubator/syncope/trunk/core/src/test/java/org/syncope/core/rest/NotificationTestITCase.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/java/org/syncope/core/rest/NotificationTestITCase.java?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/java/org/syncope/core/rest/NotificationTestITCase.java (original)
+++ incubator/syncope/trunk/core/src/test/java/org/syncope/core/rest/NotificationTestITCase.java Wed Mar 28 15:29:47 2012
@@ -29,6 +29,7 @@ import org.syncope.client.search.NodeCon
 import org.syncope.client.to.NotificationTO;
 import org.syncope.client.validation.SyncopeClientCompositeErrorException;
 import org.syncope.client.validation.SyncopeClientException;
+import org.syncope.types.IntMappingType;
 import org.syncope.types.SyncopeClientExceptionType;
 import org.syncope.types.TraceLevel;
 
@@ -65,8 +66,8 @@ public class NotificationTestITCase exte
         AttributeCond fullnameLeafCond2 = new AttributeCond(AttributeCond.Type.LIKE);
         fullnameLeafCond2.setSchema("fullname");
         fullnameLeafCond2.setExpression("%i%");
-        NodeCond about = NodeCond.getAndCond(NodeCond.getLeafCond(fullnameLeafCond1), NodeCond
-                .getLeafCond(fullnameLeafCond2));
+        NodeCond about = NodeCond.getAndCond(NodeCond.getLeafCond(fullnameLeafCond1), NodeCond.getLeafCond(
+                fullnameLeafCond2));
 
         notificationTO.setAbout(about);
 
@@ -76,12 +77,16 @@ public class NotificationTestITCase exte
 
         notificationTO.setRecipients(recipients);
 
+        notificationTO.setRecipientAttrName("email");
+        notificationTO.setRecipientAttrType(IntMappingType.UserSchema);
+
         notificationTO.setSender("syncope@syncope-idm.org");
         notificationTO.setSubject("Test notification");
         notificationTO.setTemplate("test");
 
-        NotificationTO actual = restTemplate.postForObject(BASE_URL + "notification/create.json", notificationTO,
-                NotificationTO.class);
+        NotificationTO actual =
+                restTemplate.postForObject(BASE_URL + "notification/create.json", notificationTO, NotificationTO.class);
+        
         assertNotNull(actual);
         assertNotNull(actual.getId());
         notificationTO.setId(actual.getId());
@@ -122,8 +127,7 @@ public class NotificationTestITCase exte
 
         SyncopeClientException exception = null;
         try {
-            restTemplate
-                    .getForObject(BASE_URL + "notification/read/{notificationId}.json", NotificationTO.class, "101");
+            restTemplate.getForObject(BASE_URL + "notification/read/{notificationId}.json", NotificationTO.class, "101");
         } catch (SyncopeClientCompositeErrorException e) {
             exception = e.getException(SyncopeClientExceptionType.NotFound);
         }

Modified: incubator/syncope/trunk/core/src/test/resources/content.xml
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/resources/content.xml?rev=1306418&r1=1306417&r2=1306418&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/resources/content.xml (original)
+++ incubator/syncope/trunk/core/src/test/resources/content.xml Wed Mar 28 15:29:47 2012
@@ -23,7 +23,6 @@ under the License.
   <SyncopeConf confKey="token.expireTime" confValue="60"/>
   <SyncopeConf confKey="smtp.host" confValue="not-existing"/>
   <SyncopeConf confKey="smtp.port" confValue="25"/>
-  <SyncopeConf confKey="email.schema" confValue="email"/>
   <SyncopeConf confKey="connid.bundles.directory" confValue="${bundles.directory}"/>
   <SyncopeConf confKey="password.cipher.algorithm" confValue="MD5"/>
   <SyncopeConf confKey="createRequest.allowed" confValue="true"/>
@@ -593,10 +592,12 @@ under the License.
     
   <Notification id="100" sender="test@syncope-idm.org" subject="Test subject" template="test" selfAsRecipient="0" traceLevel="ALL"
                 xmlAbout="%3Corg.syncope.client.search.NodeCond%3E%0A++%3Ctype%3EAND%3C%2Ftype%3E%0A++%3CleftNodeCond%3E%0A++++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++++%3CattributeCond%3E%0A++++++%3Ctype%3ELIKE%3C%2Ftype%3E%0A++++++%3Cschema%3Efullname%3C%2Fschema%3E%0A++++++%3Cexpression%3E%25o%25%3C%2Fexpression%3E%0A++++%3C%2FattributeCond%3E%0A++%3C%2FleftNodeCond%3E%0A++%3CrightNodeCond%3E%0A++++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++++%3CattributeCond%3E%0A++++++%3Ctype%3ELIKE%3C%2Ftype%3E%0A++++++%3Cschema%3Efullname%3C%2Fschema%3E%0A++++++%3Cexpression%3E%25i%25%3C%2Fexpression%3E%0A++++%3C%2FattributeCond%3E%0A++%3C%2FrightNodeCond%3E%0A%3C%2Forg.syncope.client.search.NodeCond%3E"
-                xmlRecipients="%3Corg.syncope.client.search.NodeCond%3E%0A++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++%3CmembershipCond%3E%0A++++%3CroleId%3E7%3C%2FroleId%3E%0A++%3C%2FmembershipCond%3E%0A%3C%2Forg.syncope.client.search.NodeCond%3E"/>
+                xmlRecipients="%3Corg.syncope.client.search.NodeCond%3E%0A++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++%3CmembershipCond%3E%0A++++%3CroleId%3E7%3C%2FroleId%3E%0A++%3C%2FmembershipCond%3E%0A%3C%2Forg.syncope.client.search.NodeCond%3E"
+                recipientAttrType="UserSchema" recipientAttrName="email"/>
   <Notification id="101" sender="test@syncope-idm.org" subject="Test subject" template="test" selfAsRecipient="0" traceLevel="ALL"
                 xmlAbout="%3Corg.syncope.client.search.NodeCond%3E%0A++%3Ctype%3EAND%3C%2Ftype%3E%0A++%3CleftNodeCond%3E%0A++++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++++%3CattributeCond%3E%0A++++++%3Ctype%3ELIKE%3C%2Ftype%3E%0A++++++%3Cschema%3Efullname%3C%2Fschema%3E%0A++++++%3Cexpression%3E%25o%25%3C%2Fexpression%3E%0A++++%3C%2FattributeCond%3E%0A++%3C%2FleftNodeCond%3E%0A++%3CrightNodeCond%3E%0A++++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++++%3CattributeCond%3E%0A++++++%3Ctype%3ELIKE%3C%2Ftype%3E%0A++++++%3Cschema%3Efullname%3C%2Fschema%3E%0A++++++%3Cexpression%3E%25i%25%3C%2Fexpression%3E%0A++++%3C%2FattributeCond%3E%0A++%3C%2FrightNodeCond%3E%0A%3C%2Forg.syncope.client.search.NodeCond%3E"
-                xmlRecipients="%3Corg.syncope.client.search.NodeCond%3E%0A++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++%3CmembershipCond%3E%0A++++%3CroleId%3E7%3C%2FroleId%3E%0A++%3C%2FmembershipCond%3E%0A%3C%2Forg.syncope.client.search.NodeCond%3E"/>
+                xmlRecipients="%3Corg.syncope.client.search.NodeCond%3E%0A++%3Ctype%3ELEAF%3C%2Ftype%3E%0A++%3CmembershipCond%3E%0A++++%3CroleId%3E7%3C%2FroleId%3E%0A++%3C%2FmembershipCond%3E%0A%3C%2Forg.syncope.client.search.NodeCond%3E"
+                recipientAttrType="UserSchema" recipientAttrName="email"/>
   <Notification_events Notification_id="100" events="unexisting1"/>
   <Notification_events Notification_id="100" events="unexisting2"/>
   <Notification_events Notification_id="101" events="unexisting1"/>