Scarab commit: svn commit: r10763 - trunk/src: conf/classes conf/conf java/org/tigris/scarab/actions java/org/tigris/scarab/actions/admin java/org/tigris/scarab/actions/base java/org/tigris/scarab/notification java/org/tigris/scarab/om java/org/tigris/scarab/tools java/org/tigris/scarab/util schema sql sql/upgrade webapp/WEB-INF/templates/navigations webapp/WEB-INF/templates/screens/admin webapp/WEB-INF/templates/screens/notifications webapp/images
Hussayn Dabbous <[email protected]>
| Newsgroups | gmane.comp.java.scarab.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: dabbous
Date: 2009-06-27 07:44:10-0700
New Revision: 10763
Added:
trunk/src/java/org/tigris/scarab/notification/Notification.java
trunk/src/java/org/tigris/scarab/om/NotificationRule.java
trunk/src/java/org/tigris/scarab/om/NotificationRuleManager.java
trunk/src/java/org/tigris/scarab/om/NotificationRulePeer.java
trunk/src/java/org/tigris/scarab/tools/ScarabUserTool.java
trunk/src/sql/upgrade/upgrade-0.23-notification.sql
trunk/src/webapp/images/customize.gif (contents, props changed)
Removed:
trunk/src/java/org/tigris/scarab/om/NotificationFilter.java
trunk/src/java/org/tigris/scarab/om/NotificationFilterManager.java
trunk/src/java/org/tigris/scarab/om/NotificationFilterPeer.java
Modified:
trunk/src/conf/classes/ScarabBundle_de.properties
trunk/src/conf/classes/ScarabBundle_en.properties
trunk/src/conf/conf/TurbineResources.properties
trunk/src/java/org/tigris/scarab/actions/ChangeNotificationStatus.java
trunk/src/java/org/tigris/scarab/actions/admin/ConditionEdit.java
trunk/src/java/org/tigris/scarab/actions/base/ScarabTemplateAction.java
trunk/src/java/org/tigris/scarab/notification/ScarabNotificationManager.java
trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java
trunk/src/java/org/tigris/scarab/om/Attribute.java
trunk/src/java/org/tigris/scarab/om/AttributeOptionPeer.java
trunk/src/java/org/tigris/scarab/om/ConditionManager.java
trunk/src/java/org/tigris/scarab/om/Conditioned.java
trunk/src/java/org/tigris/scarab/om/Issue.java
trunk/src/java/org/tigris/scarab/om/Module.java
trunk/src/java/org/tigris/scarab/om/RModuleAttribute.java
trunk/src/java/org/tigris/scarab/om/RModuleIssueType.java
trunk/src/java/org/tigris/scarab/om/RModuleOption.java
trunk/src/java/org/tigris/scarab/om/ScarabModule.java
trunk/src/java/org/tigris/scarab/om/Transition.java
trunk/src/java/org/tigris/scarab/tools/ScarabGlobalTool.java
trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java
trunk/src/java/org/tigris/scarab/util/Email.java
trunk/src/java/org/tigris/scarab/util/ScarabConstants.java
trunk/src/schema/scarab-schema.xml
trunk/src/sql/scarab-id-table-init.sql
trunk/src/webapp/WEB-INF/templates/navigations/Administration.vm
trunk/src/webapp/WEB-INF/templates/screens/admin/ConditionEdit.vm
trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationCustomize.vm
trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationList.vm
Log:
Added new features to NotificationManager
Details:
- Added ScarabUserTool to stop growth of ScarabGlobalTool and ScarabRequestTool (work in progress)
- Replaced NotificationFilter to NotificationRule and added new column RULE_ID for conditional notification sending
- Added and/or operator to conditions (only implemented for Notifications, other checkers presume operator==OR)
- Added new table columns to SCARAB_CONDITION (USER_ID and OPERATOR)
- Now EmailArchive string may contain normal Scarab users besides fully defined mail addresses. The benefit of
using Scarab users is, that for them the notification conditions are executed, hence you could add very sophisticated
archive system, where issues could be routed to differnet archivers (or QA assistants for example) depending on
the issue content.
- Added SCARAB_NOTIFICATION_RULE to id_table
- Added upgrade script src/sql/upgrade/upgrade-0.23-notification.sql
- Moved notification customizing to left navigation bar.
- Integrated Notification conditions into the ConditionEdit.vm
- Added condition editor to Notification customization
Modified: trunk/src/conf/classes/ScarabBundle_de.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_de.properties?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/conf/classes/ScarabBundle_de.properties (original)
+++ trunk/src/conf/classes/ScarabBundle_de.properties 2009-06-27 07:44:10-0700
@@ -207,10 +207,13 @@
Modification=Ãnderung
Creation=Erstellung
Notification=Mitteilung
-NotificationList=Mitteilungen
+Notifications=Mitteilungen
+NotificationList=Offene Mitteilungen
NoNotifications=Zur Zeit liegen keine Mitteilungen für Sie vor
-EditNotificationRules=Sicht Anpassen ...
-CustomizeNotifications=Mitteilungen anpassen...
+EditNotificationRules¾nachrichtigungsregeln
+CustomizeNotifications¾nachrichtigungsregeln anpassen...
+NotificationConditions¾nachrichtigungsregeln
+NoNotificationConditionsDefined=Keine Benachrichtigungsregeln definiert
GeneralInformation=Allgemeine Information
MailModifiedBy=Geändert durch
MailCreatedBy=Erstellt durch
@@ -1997,6 +2000,7 @@
UQCP2S1=Selektieren Sie für diese Sektion die Attribute gegen die Sie suchen möchten. Dann geben Sie einen Ausdruck an nach dem gesucht werden soll. Die Attribute werden nach allen Begriffen innerhalb des Suchausdrucks durchsucht. Als Beispiel hat das Game Projekt die Textattribute
SummaryDescr=Zusammenfassung, Beschreibung, Handlung
and=und
+or=oder
ErrorMessageþhlermeldung.
UQCP3=Sie interessieren sich für alle Tickets die in Zusammenhang mit der Verwendung eines Joysticks stehen. Sie können eines, mehrere oder alle Textattribute selektieren und dann den Suchbegriff "joystick" eingeben. Wenn die Suche gestartet ist werden alle Einträge in den gewählten Attributen nach dem Begriff "joystick" durchsucht.
UQCP4=Sie können in diesem Formular angeben wie Sie die Suchresultate angezeigt haben möchten. Sie können dabei auswählen nach welchem Attribut sortiert werden soll und wieviele Tickets pro Seite Sie angezeigt haben möchten.
@@ -2202,8 +2206,9 @@
ConditionOnTransition=Transition in "{0}" attribute
ConditionallyRequiredAttribute=Dieses Attribut muà angegeben werden, um die Information vollständig zu haben.
ConditionsCurrentValue=Aktueller Wert
-ConditionsExplanation1=Diese Bedingung wird genau dann erfüllt (wahr), wenn mindestens eines der unten ausgewählten Attribut-Werte Paare in einem Ticket existiert. Sie können für jedes Attribut mehrere Attributwerte auswählen.
-ConditionsExplanation2=Klicken Sie auf "Bedingungen zurücksetzen", wenn Sie die Regeln löschen wollen.
+ConditionsExplanation1=Diese Bedingung wird genau dann erfüllt (wahr), wenn mindestens eines der unten ausgewählten Attribut-Werte Paare in einem Ticket existiert. Sie können hier für jedes Attribut mehrere Attributwerte auswählen (mit der SHIFT- oder ALT-Taste!).
+ConditionsExplanation2=Sie können die logische Kombination von Attributen auch mit "und" verknüpfen. Dann muà in einem Ticket aus jedem Attribut jeweils eine der hier gewählten Optionen aktiviert sein, damit die Bedingung insgesamt erfüllt ist.
+ConditionsExplanation3=Klicken Sie auf "Bedingungen zurücksetzen", wenn Sie alle Regeln löschen wollen.
ConditionsNewValue=Neuer Wert
ConditionsSetOn¾dingung erfüllt
CustomMimeType¾nutzerdefinierterMIME Type
Modified: trunk/src/conf/classes/ScarabBundle_en.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_en.properties?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/conf/classes/ScarabBundle_en.properties (original)
+++ trunk/src/conf/classes/ScarabBundle_en.properties 2009-06-27 07:44:10-0700
@@ -224,10 +224,13 @@
Modification=Modification
Creation=Creation
Notification=Notification
-NotificationList=Notifications
+Notifications=Notifications
+NotificationList=pending Notifications
NoNotifications=Your personal Notification list is empty.
-EditNotificationRules=Customize View ...
-CustomizeNotifications=Customize notifications...
+EditNotificationRules=Notification rules
+CustomizeNotifications=Customize notification conditions...
+NotificationConditions=Notification Conditions
+NoNotificationConditionsDefined=No Notification Conditions defined
GeneralInformation=General Information
MailModifiedBy=Modified by
MailCreatedBy=Created by
@@ -2069,6 +2072,7 @@
UQCP2S1=For this section, select the attributes you would like to search against then enter a search string. Each attribute will be searched for every term that appears in your search string. For instance, the Game project has the
SummaryDescr=Summary, Description, Story-line
and=and
+or=or
ErrorMessage=Error message
UQCP3=string attributes. You are interested in any issue that involves the usage of a joystick. You can select one, some or all of the text attributes and then enter "joystick" in the search string. Once the search is initiated, all entries in the attributes you have chosen will be searched for the term "joystick".
UQCP4=You can use this form to determine how you would like the search results displayed. You can select what attribute you would like the results ordered by as well as the number of issues you would like to see per page.
@@ -2292,7 +2296,8 @@
TransitionsRoleNeeded=Role needed
ConditionDefinition=Condition definition
ConditionsExplanation1=This condition will evaluate to "true" in a given issue whenever the issue has any of the attributes values selected in the lists below. You can choose multiple values holding the SHIFT or CTRL keys.
-ConditionsExplanation2=Click on "Clear Conditions" if you want all the conditions cleared.
+ConditionsExplanation2=Multiple options within one attribute are always combined with "or" (default). But options across attributes can be combined with "and" or "or".
+ConditionsExplanation3=Click on "Clear Conditions" if you want all the conditions cleared.
ConditionsSetOn=Condition set on
ConditionsCurrentValue=Current value
ConditionsNewValue=New value
Modified: trunk/src/conf/conf/TurbineResources.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/conf/TurbineResources.properties?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/conf/conf/TurbineResources.properties (original)
+++ trunk/src/conf/conf/TurbineResources.properties 2009-06-27 07:44:10-0700
@@ -659,6 +659,7 @@
scarab.email.assignissue.template=ModifyIssue.vm
scarab.email.moveissue.template=MoveIssue.vm
+services.PullService.tool.request.scarabU=org.tigris.scarab.tools.ScarabUserTool
services.PullService.tool.request.scarabR=org.tigris.scarab.tools.ScarabRequestTool
services.PullService.tool.request.l10n=org.tigris.scarab.tools.ScarabLocalizationTool
services.PullService.tool.global.scarabG=org.tigris.scarab.tools.ScarabGlobalTool
Modified: trunk/src/java/org/tigris/scarab/actions/ChangeNotificationStatus.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/ChangeNotificationStatus.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/actions/ChangeNotificationStatus.java (original)
+++ trunk/src/java/org/tigris/scarab/actions/ChangeNotificationStatus.java 2009-06-27 07:44:10-0700
@@ -10,12 +10,11 @@
import org.apache.turbine.RunData;
import org.apache.turbine.TemplateContext;
import org.tigris.scarab.actions.base.ScarabTemplateAction;
-import org.tigris.scarab.notification.ActivityType;
import org.tigris.scarab.notification.NotificationManagerFactory;
import org.tigris.scarab.om.Module;
-import org.tigris.scarab.om.NotificationFilter;
-import org.tigris.scarab.om.NotificationFilterManager;
-import org.tigris.scarab.om.NotificationFilterPeer;
+import org.tigris.scarab.om.NotificationRule;
+import org.tigris.scarab.om.NotificationRuleManager;
+import org.tigris.scarab.om.NotificationRulePeer;
import org.tigris.scarab.om.NotificationStatus;
import org.tigris.scarab.om.NotificationStatusPeer;
import org.tigris.scarab.om.ScarabUser;
@@ -195,9 +194,9 @@
Integer moduleId = module.getModuleId();
- // The filterMap contains all filters for this user and this module
- NotificationFilterPeer nfp = new NotificationFilterPeer();
- Map filterMap = nfp.getCustomization(moduleId, userId);
+ // The ruleMap contains all rules for this user and this module
+ NotificationRulePeer nfp = new NotificationRulePeer();
+ Map<String, List<NotificationRule>> ruleMap = NotificationRulePeer.getCustomization(moduleId, userId);
// The list of activityTypes
ScarabGlobalTool scarabG = getScarabGlobalTool(context);
@@ -207,106 +206,113 @@
while(iter.hasNext())
{
String code = (String)iter.next();
- ActivityType activityType = ActivityType.getActivityType(code);
boolean theStatus = data.getParameters().getBoolean(code+":status");
boolean theSendSelf = data.getParameters().getBoolean(code+":self");
boolean theSendFailure = data.getParameters().getBoolean(code+":fail");
Integer managerId = NotificationManagerFactory.getInstance().getManagerId();
- NotificationFilter filter = NotificationFilter.createDefaultFilter
- (
- moduleId,
- userId,
- managerId,
- activityType
- );
-
- markUpdateOrNew(filter);
+ NotificationRule rule = null;
+ List<NotificationRule> rules = ruleMap.get(code);
+ if(rules.size() == 0)
+ {
+ rule = NotificationRule.createDefaultRule
+ (
+ moduleId,
+ userId,
+ managerId,
+ code
+ );
+ }
+ else
+ {
+ rule = rules.get(0);
+ }
+ markUpdateOrNew(rule);
// adjust the new attribute values
- filter.setSendSelf(theSendSelf);
- filter.setSendFailures(theSendFailure);
- filter.setFilterState(theStatus);
+ rule.setSendSelf(theSendSelf);
+ rule.setSendFailures(theSendFailure);
+ rule.setFilterState(theStatus);
// finally modify in database.
- modifyInDatabase(filter);
+ modifyInDatabase(rule);
}
scarabR.setConfirmMessage(L10NKeySet.ChangesSaved);
}
/**
- * Check whether the filter needs to be created, updated or removed
+ * Check whether the rule needs to be created, updated or removed
* and process the particular database call.
* from the database.
- * @param filter
+ * @param rule
* @throws TorqueException
* @throws Exception
*/
- private void modifyInDatabase(NotificationFilter filter) throws TorqueException, Exception
+ private void modifyInDatabase(NotificationRule rule) throws TorqueException, Exception
{
- if (equalsDefaultCustomization(filter))
+ if (equalsDefaultCustomization(rule))
{
- if (filter.isNew())
+ if (rule.isNew())
{
- // don't need to create this filter
+ // don't need to create this rule
}
else
{
- // can safely remove this filter
- ObjectKey pk = filter.getPrimaryKey();
- NotificationFilterPeer.doDelete(pk);
+ // can safely remove this rule
+ ObjectKey pk = rule.getPrimaryKey();
+ NotificationRulePeer.doDelete(pk);
}
}
else
{
- // need to store this filter
- filter.save();
+ // need to store this rule
+ rule.save();
}
}
/**
- * Check wether the given filter is allready contained
+ * Check wether the given rule is allready contained
* in the repository and mark it either as new or
* already existing.
- * @param filter
+ * @param rule
* @return
*/
- private void markUpdateOrNew(NotificationFilter filter)
+ private void markUpdateOrNew(NotificationRule rule)
{
// Check if the entry already exists in database:
- ObjectKey pk = filter.getPrimaryKey();
+ ObjectKey pk = rule.getPrimaryKey();
try
{
- if (NotificationFilterManager.getInstance(pk) != null)
+ if (NotificationRuleManager.getInstance(pk) != null)
{
- filter.setNew(false);
+ rule.setNew(false);
}
}
catch (Exception e)
{
- filter.setNew(true);
+ rule.setNew(true);
}
}
/**
* Check equality to default customization.
- * This filter is equal to the default filter, when it
+ * This rule is equal to the default rule, when it
* is equal in all attributes.
- * Currently the default filter is hard coded, see below
- * @param filter
+ * Currently the default rule is hard coded, see below
+ * @param rule
* @return
*/
- private boolean equalsDefaultCustomization(NotificationFilter filter)
+ private boolean equalsDefaultCustomization(NotificationRule rule)
{
- // currently we assume, that the filter is
+ // currently we assume, that the rule is
// equivalent to the default setting when:
- if (!filter.getFilterState()) return false; // filter enabled
- if (filter.getSendSelf()) return false; // dont send to me
- if (filter.getSendFailures()) return false; // dont send failures
+ if (!rule.getFilterState()) return false; // rule enabled
+ if (rule.getSendSelf()) return false; // dont send to me
+ if (rule.getSendFailures()) return false; // dont send failures
// this behaviour will be changed as soon as default settings
// are available.
Modified: trunk/src/java/org/tigris/scarab/actions/admin/ConditionEdit.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/admin/ConditionEdit.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/actions/admin/ConditionEdit.java (original)
+++ trunk/src/java/org/tigris/scarab/actions/admin/ConditionEdit.java 2009-06-27 07:44:10-0700
@@ -46,7 +46,10 @@
* individuals on behalf of Collab.Net.
*/
+import java.util.List;
+
import org.apache.fulcrum.intake.model.Group;
+import org.apache.fulcrum.security.entity.User;
import org.apache.torque.TorqueException;
import org.apache.torque.util.Criteria;
import org.apache.turbine.RunData;
@@ -55,15 +58,18 @@
import org.tigris.scarab.actions.base.RequireLoginFirstAction;
import org.tigris.scarab.om.Attribute;
import org.tigris.scarab.om.AttributeManager;
+import org.tigris.scarab.om.Condition;
import org.tigris.scarab.om.ConditionManager;
import org.tigris.scarab.om.ConditionPeer;
import org.tigris.scarab.om.Module;
+import org.tigris.scarab.om.NotificationRulePeer;
import org.tigris.scarab.om.RModuleAttribute;
import org.tigris.scarab.om.RModuleAttributeManager;
import org.tigris.scarab.om.RModuleAttributePeer;
import org.tigris.scarab.om.RModuleIssueType;
import org.tigris.scarab.om.RModuleIssueTypeManager;
import org.tigris.scarab.om.RModuleIssueTypePeer;
+import org.tigris.scarab.om.ScarabUser;
import org.tigris.scarab.om.Transition;
import org.tigris.scarab.om.TransitionManager;
import org.tigris.scarab.tools.ScarabRequestTool;
@@ -80,7 +86,7 @@
updateObject(data, context, null);
}
- private void delete(RunData data) throws TorqueException, Exception
+ private void delete(RunData data, TemplateContext context) throws TorqueException, Exception
{
int nObjectType = data.getParameters().getInt("obj_type");
Criteria crit = new Criteria();
@@ -101,6 +107,20 @@
crit.add(ConditionPeer.MODULE_ID, data.getParameters().getInt("module_id"));
crit.add(ConditionPeer.ISSUE_TYPE_ID, data.getParameters().getInt("issueTypeId"));
break;
+ case ScarabConstants.NOTIFICATION_ATTRIBUTE_OBJECT:
+ ScarabRequestTool scarabR = getScarabRequestTool(context);
+ ScarabUser user = (ScarabUser)data.getUser();
+ if(user == null)
+ {
+ throw new TorqueException("No user found in RunData during Notification customization (constraints on attributes)");
+ }
+ Module module = scarabR.getCurrentModule();
+ if(module == null)
+ {
+ throw new TorqueException("No module found in RunData during Notification customization (constraints on attributes)");
+ }
+ NotificationRulePeer.deleteConditions(user, module);
+ return;
}
ConditionPeer.doDelete(crit);
ConditionManager.clear();
@@ -110,40 +130,57 @@
private void updateObject(RunData data, TemplateContext context, Integer aConditions[]) throws Exception
{
ScarabRequestTool scarabR = getScarabRequestTool(context);
+ Integer operator = data.getParameters().getInteger("combineWith");
switch (data.getParameters().getInt("obj_type"))
{
case ScarabConstants.TRANSITION_OBJECT:
Transition transition = scarabR.getTransition(data.getParameters().getInteger("transition_id"));
- transition.setConditionsArray(aConditions);
+ transition.setConditionsArray(aConditions, operator);
transition.save();
TransitionManager.getMethodResult().remove(transition, TransitionManager.GET_CONDITIONS);
+ AttributeManager.clear();
break;
case ScarabConstants.GLOBAL_ATTRIBUTE_OBJECT:
Attribute attribute = scarabR.getAttribute(data.getParameters().getInteger("attId"));
- attribute.setConditionsArray(aConditions);
+ attribute.setConditionsArray(aConditions, operator);
attribute.save();
+ AttributeManager.clear();
break;
case ScarabConstants.MODULE_ATTRIBUTE_OBJECT:
RModuleAttribute rma = RModuleAttributePeer.retrieveByPK(data.getParameters().getInteger("moduleId"), data.getParameters().getInteger("attId"), data.getParameters().getInteger("issueTypeId"));
- rma.setConditionsArray(aConditions);
+ rma.setConditionsArray(aConditions, operator);
RModuleAttributeManager.clear();
ConditionManager.clear();
rma.save(); /** TODO: do we need it? **/
+ AttributeManager.clear();
break;
case ScarabConstants.BLOCKED_MODULE_ISSUE_TYPE_OBJECT:
RModuleIssueType rmit = RModuleIssueTypePeer.retrieveByPK(scarabR.getCurrentModule().getModuleId(), data.getParameters().getInteger("issuetypeid"));
- rmit.setConditionsArray(aConditions);
+ rmit.setConditionsArray(aConditions, operator);
rmit.save();
RModuleIssueTypeManager.clear();
ConditionManager.clear();
+ AttributeManager.clear();
+ break;
+ case ScarabConstants.NOTIFICATION_ATTRIBUTE_OBJECT:
+ ScarabUser user = (ScarabUser)data.getUser();
+ if(user == null)
+ {
+ throw new TorqueException("No user found in RunData during Notification customization (constraints on attributes)");
+ }
+ Module module = scarabR.getCurrentModule();
+ if(module == null)
+ {
+ throw new TorqueException("No module found in RunData during Notification customization (constraints on attributes)");
+ }
+ NotificationRulePeer.saveConditions(user, module, aConditions, operator);
break;
}
- AttributeManager.clear();
}
public void doSave(RunData data, TemplateContext context) throws Exception
{
- this.delete(data);
+ this.delete(data, context);
IntakeTool intake = getIntakeTool(context);
Group attrGroup = intake.get("ConditionEdit", IntakeTool.DEFAULT_KEY);
Integer aConditions[] = ((Integer[])attrGroup.get("ConditionsArray").getValue());
Modified: trunk/src/java/org/tigris/scarab/actions/base/ScarabTemplateAction.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/base/ScarabTemplateAction.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/actions/base/ScarabTemplateAction.java (original)
+++ trunk/src/java/org/tigris/scarab/actions/base/ScarabTemplateAction.java 2009-06-27 07:44:10-0700
@@ -57,6 +57,7 @@
import org.apache.turbine.tool.IntakeTool;
import org.tigris.scarab.tools.ScarabLocalizationTool;
import org.tigris.scarab.tools.ScarabRequestTool;
+import org.tigris.scarab.tools.ScarabUserTool;
import org.tigris.scarab.util.ScarabConstants;
/**
@@ -96,6 +97,15 @@
}
/**
+ * Helper method to retrieve the ScarabUserTool from the Context
+ */
+ public ScarabUserTool getScarabUserTool(TemplateContext context)
+ {
+ return (ScarabUserTool)context
+ .get(ScarabConstants.SCARAB_USER_TOOL);
+ }
+
+ /**
* Helper method to retrieve the ScarabLocalizationTool from the Context
*/
protected final ScarabLocalizationTool
Added: trunk/src/java/org/tigris/scarab/notification/Notification.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/notification/Notification.java?view=markup&pathrev763
=============================================================================--- (empty file)
+++ trunk/src/java/org/tigris/scarab/notification/Notification.java 2009-06-27 07:44:10-0700
@@ -0,0 +1,298 @@
+package org.tigris.scarab.notification;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import org.apache.log4j.Logger;
+import org.apache.torque.TorqueException;
+import org.tigris.scarab.om.Attribute;
+import org.tigris.scarab.om.AttributeOption;
+import org.tigris.scarab.om.AttributeOptionManager;
+import org.tigris.scarab.om.AttributeValue;
+import org.tigris.scarab.om.Condition;
+import org.tigris.scarab.om.Conditioned;
+import org.tigris.scarab.om.Issue;
+import org.tigris.scarab.om.Module;
+import org.tigris.scarab.om.NotificationRule;
+import org.tigris.scarab.om.NotificationRulePeer;
+import org.tigris.scarab.om.ScarabUser;
+import org.tigris.scarab.util.Log;
+
+public class Notification implements Conditioned
+{
+ private List<Condition> conditions;
+ private Set<Integer> optionIds;
+ private List<NotificationRule> rules;
+ private Issue issue;
+ private ScarabUser user;
+ private Module module;
+
+ public static Logger log = Log.get(Notification.class.getName());
+
+
+ /**
+ * This is a NotificationPlaceholder. It is NOT associated to an issue
+ * and it serves only as support for the NotificationCondition editor.
+ * It could be used as generic instance, which can be dynamically associated
+ * using setIssue() (see below)
+ **/
+ public Notification(ScarabUser user, Module module) throws TorqueException
+ {
+ this.user = user;
+ this.module = module;
+
+ this.conditions = null; // creation on demand
+ this.optionIds = null; // creation on demand
+ this.rules = null; // creation on demand
+ this.issue = null; // no issue --> for ConditionEditor only
+ }
+
+ /**
+ * Create a new Notification instance for a given user/issue pair
+ * This instance can be checked for send conditions. It is currently
+ * used solely in the Notificationmanager
+ **/
+ public Notification(ScarabUser user, Issue issue ) throws TorqueException
+ {
+ this.user = user;
+ this.module = issue.getModule();
+ this.issue = issue;
+ this.rules = null;
+ this.conditions = null;
+ }
+
+ /**
+ * set the issue for this notification (currently not used and added
+ * for future features)
+ */
+ public void setIssue(Issue issue) throws TorqueException
+ {
+ this.module = issue.getModule();
+ this.issue = issue;
+ this.conditions = null;
+ this.rules = null;
+ this.optionIds = null;
+ }
+
+ /**
+ * Get the list of Condition instances for this context
+ * the List contains an array of Integers
+ */
+ public Integer[] getConditionsArray()
+ {
+ Integer[] entries = new Integer[conditions.size()];
+ Iterator<Condition> iter;
+ try {
+ iter = getConditions().iterator();
+ } catch (TorqueException e) {
+ throw new RuntimeException(e);
+ }
+ int index = 0;
+ while(iter.hasNext())
+ {
+ Condition condition = iter.next();
+ entries[index] = condition.getConditionId().intValue();
+ }
+ return entries;
+ }
+
+ /**
+ * Return the boolean operator to be used to combine different attributes.
+ * Although the operator is fully implemented, each Conditioned class
+ * still must implement its usage. Currently the operator is only
+ * active for Notification conditions.
+ * @return
+ */
+ public Integer getConditionOperator()
+ {
+ Integer operator = 0;
+ List<Condition> conditions;
+ try {
+ conditions = getConditions();
+ } catch (TorqueException e) {
+ // TODO Auto-generated catch block
+ throw new RuntimeException(e);
+ }
+ if(conditions.size() > 0)
+ {
+ operator = conditions.get(0).getOperator();
+ }
+ return operator;
+ }
+
+
+ /**
+ * Return s true, if the user has defined conditions for this
+ * module via "condition rules" in the admin toolbox (in scarab GUI)
+ */
+ public boolean isConditioned()
+ {
+ boolean conditioned;
+ try {
+ conditioned = getConditions().size() > 0;
+ } catch (TorqueException e)
+ {
+ throw new RuntimeException(e);
+ }
+ return conditioned;
+ }
+
+ /**
+ * Check, if the given optionId is contained in the condition list
+ **/
+ public boolean isRequiredIf(Integer optionID) throws TorqueException
+ {
+ boolean isRequired = getOptionIds().contains(optionID);
+ return isRequired;
+ }
+
+ /**
+ * For Condition editing: Create a conditionset for the associated user/module
+ * combination containing the given list of OptionIds
+ **/
+ public void setConditionsArray(Integer[] optionId, Integer operator) throws TorqueException
+ {
+ NotificationRulePeer.saveConditions(user, module, optionId, operator);
+ }
+
+ /**
+ * Get the list of Condition ionstances which are defined for the given
+ * user/module combination
+ **/
+ public List<Condition> getConditions() throws TorqueException
+ {
+ if(conditions == null)
+ {
+ conditions = NotificationRulePeer.getConditions(user, module);
+ }
+ return conditions;
+ }
+
+ /**
+ * Get the send rules. Currently the returned list contains 18 entries, one for each activityType.
+ * Explanation: Each Activity_type has an associated send rule which allows to enable/disable
+ * notification sending depending on what modifications have been made on an issue.
+ * E.g. you could create a rule, which effectively disables any notification to the user
+ * when an issue-attachment is added, or when a comment is added, etc.
+ * The interface on the Scarab GUI is in the admin toolbox ("notification rules")
+ **/
+ public List<NotificationRule> getRules() throws TorqueException
+ {
+ if(rules == null)
+ {
+ NotificationRulePeer.getNotificationRules(user, module);
+ }
+ return rules;
+ }
+
+ /**
+ * Get the list of OptionIDs associated to the set of conditions
+ * Take care to NOT intermix conditions and rules. A condition
+ * specifies which optionId has to be set to a specific value in order
+ * to let the condition match. While a rule applies to the current issueType
+ * (and if set to disabled it disables notiofications disregarding any conditions)
+ * In order to get conditions into effect, at least one of the rules must be set
+ * to "enabled". Otherwise notification sendinjg is completely suppressed.
+ **/
+ private Set<Integer> getOptionIds() throws TorqueException
+ {
+ Iterator<Condition> iter = getConditions().iterator();
+ Set<Integer>optionIds = new HashSet<Integer>();
+ while(iter.hasNext())
+ {
+ Condition condition = iter.next();
+ Integer optionId = condition.getOptionId();
+ if(optionId != null)
+ {
+ optionIds.add(optionId);
+ }
+ }
+ return optionIds;
+ }
+
+ /**
+ * Check if the current combination of user/module/issue-content
+ * meets the conditions under whioch a notification shal be sent.
+ * Note: If the condition operator is set to "OR", any matching
+ * notification option in any attribute will return true
+ * If the operator is set to "AND" Each attribute for which options have
+ * been set must match at least one of the selected options.
+ * hence you could for instance let notifications only send when
+ * attribute status="closed" AND severity="show stopper"
+ * Note: Currently it is not possible to define multiple condition sets for
+ * one user/module pair.
+ **/
+ public boolean sendConditionsMatch() throws TorqueException
+ {
+ Map<String,AttributeValue> attributeValues = issue.getModuleOptionAttributeValuesMap();
+ List<Condition> conditions = getConditions();
+ Integer operator = getConditionOperator();
+
+ Iterator<Condition> iter = conditions.iterator();
+ Set<Integer>attributeIds = new HashSet<Integer>();
+
+ log.info("test sendNotification conditions -----------------------------------------------");
+
+ int matchCounter = 0;
+ while(iter.hasNext())
+ {
+ Condition condition = iter.next();
+ AttributeOption ao = condition.getAttributeOption();
+ int optionId = ao.getOptionId();
+ Attribute attribute = ao.getAttribute();
+ int attributeId = attribute.getAttributeId();
+ attributeIds.add(attributeId);
+
+ AttributeOption option = AttributeOptionManager.getInstance(optionId);
+
+ log.info("test " + attribute.getName() + "=\"" + option.getName() + "\" (att:" + + attributeId + ",opt:" + optionId+")");
+
+ Iterator<Entry<String,AttributeValue>> attvalIterator = attributeValues.entrySet().iterator();
+ while( attvalIterator.hasNext())
+ {
+ Entry<String,AttributeValue> e = attvalIterator.next();
+ AttributeValue av = e.getValue();
+ int attvalAttributeId = av.getAttributeId();
+ Attribute att = av.getAttribute();
+ AttributeOption attOpt = av.getAttributeOption();
+ if(attributeId == attvalAttributeId)
+ {
+ int aoi = av.getOptionId();
+ boolean match = aoi == optionId;
+ log.info( ((match)? "match ":" ") + att.getName() + "=\"" + attOpt.getName() + "\" (att:" + attvalAttributeId + ",opt:" + attOpt.getOptionId());
+ if( match)
+ {
+ matchCounter++;
+ if ( operator.equals(OR) )
+ {
+ log.info("SendCondition met. (any condition match terminated on first match");
+ return true; // quick exit. first match gives success.
+ }
+ break; // we can break the inner iteration (we found the match)
+ }
+
+ }
+ }
+ }
+
+ boolean match; // just in case no condition is defined, we return true
+ if(operator.equals(AND) && attributeIds.size() == matchCounter)
+ {
+ log.info("SendCondition met. (all conditions matched)");
+ match = true; // operator
+ }
+ else
+ {
+ log.info("Only " + matchCounter + " send Conditions out of "+attributeIds.size()+" match the req)uiered values");
+ match = false;
+ }
+
+ return match;
+ }
+
+
+}
Modified: trunk/src/java/org/tigris/scarab/notification/ScarabNotificationManager.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/notification/ScarabNotificationManager.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/notification/ScarabNotificationManager.java (original)
+++ trunk/src/java/org/tigris/scarab/notification/ScarabNotificationManager.java 2009-06-27 07:44:10-0700
@@ -69,7 +69,7 @@
import org.tigris.scarab.om.Issue;
import org.tigris.scarab.om.IssueManager;
import org.tigris.scarab.om.Module;
-import org.tigris.scarab.om.NotificationFilterManager;
+import org.tigris.scarab.om.NotificationRuleManager;
import org.tigris.scarab.om.NotificationStatus;
import org.tigris.scarab.om.NotificationStatusPeer;
import org.tigris.scarab.om.ScarabUser;
@@ -148,7 +148,7 @@
try
{
NotificationStatus notification = null;
- for (Iterator it = activitySet.getActivityList().iterator(); it.hasNext(); )
+ for (Iterator<Activity> it = activitySet.getActivityList().iterator(); it.hasNext(); )
{
Activity act = (Activity)it.next();
if (act.getIssue().equals(issue))
@@ -156,26 +156,36 @@
notification = new NotificationStatus(Email.getArchiveUser(), act);
NotificationStatusPeer.doInsert(notification);
- Set users = issue.getAllUsersToEmail(AttributePeer.EMAIL_TO);
+ Module module = issue.getModule();
+ Set<ScarabUser> users = issue.getAllUsersToEmail(AttributePeer.EMAIL_TO);
users.addAll(issue.getAllUsersToEmail(AttributePeer.CC_TO));
users.addAll(activitySet.getRemovedUsers(issue));
-
+
+ // Add all ScarabUsers defined in the module's ArchiveEmail string
+ // Note 1: Only those entries will be taken into account, which can
+ // be identified as valid and existing Scarab users in the local
+ // repository.
+ // Note 2: the users notification settings apply here!
+ // Note 3: All foreign EmailAddresses stored in the module's ArchiveEmail
+ // will be ignored here and later added without any constraints
+ // during actual sending of the EMail!
+ users.addAll(module.getArchivingScarabUsers());
+
// FIXME: Should we still make difference between CC & TO? If so...
// ...do we need this info in the notification_status table??
-
+
// FIXME: SCB1439. does the user really have permissions
// to view this attribute?
-
- Integer moduleId = issue.getModuleId();
+
String activityType = act.getActivityType();
- for (Iterator itusers = users.iterator(); itusers.hasNext(); )
+ for (Iterator<ScarabUser> itusers = users.iterator(); itusers.hasNext(); )
{
ScarabUser user = (ScarabUser)itusers.next();
Integer userId = user.getUserId();
boolean isSelf = userId.equals(fromUser.getUserId());
- boolean wantsNotification = NotificationFilterManager.isNotificationEnabledFor(moduleId, userId, isSelf, activityType);
+ boolean wantsNotification = NotificationRuleManager.isNotificationEnabledFor(user, issue, isSelf, activityType);
if(wantsNotification)
{
Modified: trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java (original)
+++ trunk/src/java/org/tigris/scarab/om/AbstractScarabModule.java 2009-06-27 07:44:10-0700
@@ -964,7 +964,7 @@
rma.setIssueTypeId(issueType.getIssueTypeId());
rma.setAttributeId(attribute.getAttributeId());
rma.setOrder(getLastAttribute(issueType, attributeType) + 1);
- rma.setConditionsArray(attribute.getConditionsArray());
+ rma.setConditionsArray(attribute.getConditionsArray(), attribute.getConditionOperator());
rma.save();
getRModuleAttributes(issueType, false, attributeType).add(rma);
Modified: trunk/src/java/org/tigris/scarab/om/Attribute.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Attribute.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/Attribute.java (original)
+++ trunk/src/java/org/tigris/scarab/om/Attribute.java 2009-06-27 07:44:10-0700
@@ -717,7 +717,7 @@
newAttribute.setTypeId(getTypeId());
newAttribute.setPermission(getPermission());
newAttribute.setRequiredOptionId(getRequiredOptionId());
- newAttribute.setConditionsArray(getConditionsArray());
+ newAttribute.setConditionsArray(getConditionsArray(), getConditionOperator());
newAttribute.setAction(getAction());
newAttribute.setCreatedBy(user.getUserId());
newAttribute.setCreatedDate(new Date());
@@ -978,7 +978,7 @@
return aIDs;
}
- public List getConditions() throws TorqueException
+ public List<Condition> getConditions() throws TorqueException
{
if (collConditions == null)
{
@@ -997,10 +997,11 @@
* @param aOptionId
* @throws TorqueException
*/
- public void setConditionsArray(Integer aOptionId[]) throws TorqueException
+ public void setConditionsArray(Integer aOptionId[], Integer operator) throws TorqueException
{
Criteria crit = new Criteria();
crit.add(ConditionPeer.ATTRIBUTE_ID, this.getAttributeId());
+ crit.add(ConditionPeer.OPERATOR, this.getConditionOperator());
crit.add(ConditionPeer.MODULE_ID, null);
crit.add(ConditionPeer.ISSUE_TYPE_ID, null);
crit.add(ConditionPeer.TRANSITION_ID, null);
@@ -1019,11 +1020,36 @@
cond.setModuleId(null);
cond.setIssueTypeId(null);
cond.setTransitionId(null);
+ cond.setUserId(null);
+ cond.setOperator(operator);
this.addCondition(cond);
cond.save();
}
}
}
+
+ /**
+ * Return AND or OR depending on what has been selected in the
+ * Condition Editor
+ * @return
+ * @throws TorqueException
+ */
+ public Integer getConditionOperator()
+ {
+ List<Condition> conditions;
+ try {
+ conditions = this.getConditions();
+ } catch (TorqueException e) {
+ throw new RuntimeException(e);
+ }
+ Integer operator = 0;
+ if (conditions.size() > 0)
+ {
+ operator = conditions.get(0).getOperator();
+ }
+ return operator;
+ }
+
/**
* Return true if the given attributeOptionId will make the current
* attribute required.
Modified: trunk/src/java/org/tigris/scarab/om/AttributeOptionPeer.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/AttributeOptionPeer.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/AttributeOptionPeer.java (original)
+++ trunk/src/java/org/tigris/scarab/om/AttributeOptionPeer.java 2009-06-27 07:44:10-0700
@@ -67,7 +67,8 @@
* Returns an ordered attribute_options list
* @return
*/
- public static List getSortedAttributeOptions() throws TorqueException {
+ public static List getSortedAttributeOptions() throws TorqueException
+ {
List attributeOptions = null;
final Criteria crit = new Criteria();
crit.addAscendingOrderByColumn(AttributeOptionPeer.ATTRIBUTE_ID);
@@ -77,5 +78,26 @@
return attributeOptions;
}
+ /**
+ * Returns an ordered attribute_options list
+ * @return
+ */
+ public static List<AttributeOption> getSortedAttributeOptions(Module module) throws TorqueException
+ {
+ List<Integer> rmaIds = RModuleAttribute.getRMAIds(module.getModuleId());
+ //List<Integer> rmoIds = RModuleOption.getRMOIds(module.getModuleId());
+ List<AttributeOption> attributeOptions = null;
+ final Criteria crit = new Criteria();
+
+ //SELECT * FROM scarab_attribute_option s where attribute_id in (select distinct attribute_id from scarab_r_module_attribute where module_id001);
+ crit.addIn(AttributeOptionPeer.ATTRIBUTE_ID,rmaIds);
+ crit.add(AttributeOptionPeer.DELETED,0);
+ crit.addAscendingOrderByColumn(AttributeOptionPeer.ATTRIBUTE_ID);
+ crit.addAscendingOrderByColumn(AttributeOptionPeer.OPTION_ID);
+ attributeOptions = (List<AttributeOption>)doSelect(crit);
+ attributeOptions.remove(0);
+ return attributeOptions;
+ }
+
}
Modified: trunk/src/java/org/tigris/scarab/om/ConditionManager.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/ConditionManager.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/ConditionManager.java (original)
+++ trunk/src/java/org/tigris/scarab/om/ConditionManager.java 2009-06-27 07:44:10-0700
@@ -46,9 +46,10 @@
package org.tigris.scarab.om;
-import org.apache.torque.Torque;
+import java.util.List;
+
import org.apache.torque.TorqueException;
-import org.apache.torque.om.Persistent;
+import org.apache.torque.util.Criteria;
/**
* This class manages Condition objects.
@@ -69,4 +70,5 @@
{
super();
}
+
}
Modified: trunk/src/java/org/tigris/scarab/om/Conditioned.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Conditioned.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/Conditioned.java (original)
+++ trunk/src/java/org/tigris/scarab/om/Conditioned.java 2009-06-27 07:44:10-0700
@@ -58,6 +58,19 @@
*/
public interface Conditioned
{
+ public static final Integer OR = 0;
+ public static final Integer AND = 1;
+
+ /**
+ * The logical operator to combine conditions.
+ * Currently AttributeOptions within one Attribute are always combined with OR,
+ * simply because only one option can be active within an optionAttibute.
+ * The operator returned here is meant to work between different attributes.
+ * @author hdab
+ *
+ */
+ public Integer getConditionOperator();
+
/**
* Returns the array of Ids of the conditions that will force the requirement
* of this attribute if set. Used by templates to load the combo.
@@ -66,10 +79,12 @@
public Integer[] getConditionsArray();
/**
* Load the attribute options' IDs from the template combo.
+ * operator is 0 for "or" and 1 for "and" We can not use enums here,
+ * because we will get data from velocity. Hence the 'hack' to use Integers here.
* @param aOptionId
* @throws TorqueException
*/
- public void setConditionsArray(Integer aOptionId[])
+ public void setConditionsArray(Integer aOptionId[], Integer operator)
throws TorqueException;
/**
* Return true if the given attributeOptionId will make the current
Modified: trunk/src/java/org/tigris/scarab/om/Issue.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Issue.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/Issue.java (original)
+++ trunk/src/java/org/tigris/scarab/om/Issue.java 2009-06-27 07:44:10-0700
@@ -112,6 +112,8 @@
"getAssociatedUsers";
protected static final String GET_MODULE_ATTRVALUES_MAP "getModuleAttributeValuesMap";
+ protected static final String GET_MODULE_OPTION_ATTRVALUES_MAP + "getModuleOptionAttributeValuesMap";
protected static final String GET_ATTRVALUE =
"getAttributeValue";
protected static final String GET_ATTRVALUES =
@@ -855,6 +857,56 @@
}
return result;
}
+
+ /**
+ * Same as above, but only return active attributes which are associated to AttriobuteOptions.
+ * This method is used for Notification send checking. Note that i needed to switch to the
+ * ScarabCache, while otherwise OptionAttribute values wher not correctly returned to the
+ * checker.
+ */
+ public LinkedMap getModuleOptionAttributeValuesMap()
+ throws TorqueException
+ {
+ LinkedMap result = null;
+ //Object obj = getCachedObject(GET_MODULE_OPTION_ATTRVALUES_MAP);
+ Object obj = ScarabCache.get(this, GET_MODULE_OPTION_ATTRVALUES_MAP);
+ if (obj == null)
+ {
+ List attributes = null;
+ Module module = getModule();
+ IssueType issueType = getIssueType();
+ attributes = issueType.getActiveAttributes(module);
+ Map siaValuesMap = getAttributeValuesMap();
+ result = new LinkedMap((int)(1.25*attributes.size() + 1));
+ for (int i=0; i<attributes.size(); i++)
+ {
+ String key = ((Attribute)attributes.get(i)).getName().toUpperCase();
+ AttributeValue aval;
+ if (siaValuesMap.containsKey(key))
+ {
+ aval = (AttributeValue)siaValuesMap.get(key);
+ }
+ else
+ {
+ Attribute attr = (Attribute)attributes.get(i);
+ aval = AttributeValue.getNewInstance(attr, this);
+ addAttributeValue(aval);
+ }
+ if(aval.getOptionId() != null)
+ {
+ result.put(key, aval);
+ }
+ }
+ //putCachedObject(result, GET_MODULE_OPTION_ATTRVALUES_MAP);
+ ScarabCache.put(result, this, GET_MODULE_OPTION_ATTRVALUES_MAP);
+ }
+ else
+ {
+ result = (LinkedMap)obj;
+ }
+ return result;
+ }
+
public void addAttributeValue(AttributeValue aval)
throws TorqueException
@@ -1172,12 +1224,12 @@
* @param users The list of users to append to, or
* <code>null</code> to create a new list.
*/
- protected Set getUsersToEmail(String action, Issue issue, Set users)
+ protected Set<ScarabUser> getUsersToEmail(String action, Issue issue, Set<ScarabUser> users)
throws TorqueException
{
if (users == null)
{
- users = new HashSet(1);
+ users = new HashSet<ScarabUser>(1);
}
Module module = getModule();
@@ -1231,13 +1283,13 @@
*
* @see #getUsersToEmail
*/
- public Set getAllUsersToEmail(String action) throws TorqueException
+ public Set<ScarabUser> getAllUsersToEmail(String action) throws TorqueException
{
- Set result = null;
+ Set<ScarabUser> result = null;
Object obj = ScarabCache.get(this, GET_ALL_USERS_TO_EMAIL, action);
if (obj == null)
{
- Set users = new HashSet();
+ Set<ScarabUser> users = new HashSet<ScarabUser>();
try
{
users = getUsersToEmail(action, this, users);
Modified: trunk/src/java/org/tigris/scarab/om/Module.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Module.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/Module.java (original)
+++ trunk/src/java/org/tigris/scarab/om/Module.java 2009-06-27 07:44:10-0700
@@ -50,6 +50,7 @@
import java.io.Serializable;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import org.apache.fulcrum.security.entity.Role;
import org.apache.regexp.REProgram;
@@ -457,8 +458,21 @@
/**
* All emails related to this module will have a copy sent to
* this address.
+ * @deprecated use getArchivingMailAdresses();
*/
- String getArchiveEmail();
+ String getArchiveEmail(); // all entries (Deprecated!)
+
+ /**
+ * All emails related to this module will have a copy sent to
+ * this list of EmailAdresses.
+ */
+ Set<String> getArchivingMailAddresses();
+
+ /**
+ * All emails related to this module will have a copy sent to
+ * this list of local ScarabUsers.
+ */
+ Set<ScarabUser> getArchivingScarabUsers();
/**
* The default address that is used to fill out either the From or
@@ -560,5 +574,6 @@
* @return a <code>Locale</code> value
*/
Locale getLocale();
+
}
Removed: trunk/src/java/org/tigris/scarab/om/NotificationFilter.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/NotificationFilter.java?view=markup&pathrev762
Removed: trunk/src/java/org/tigris/scarab/om/NotificationFilterManager.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/NotificationFilterManager.java?view=markup&pathrev762
Removed: trunk/src/java/org/tigris/scarab/om/NotificationFilterPeer.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/NotificationFilterPeer.java?view=markup&pathrev762
Added: trunk/src/java/org/tigris/scarab/om/NotificationRule.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/NotificationRule.java?view=markup&pathrev763
=============================================================================--- (empty file)
+++ trunk/src/java/org/tigris/scarab/om/NotificationRule.java 2009-06-27 07:44:10-0700
@@ -0,0 +1,51 @@
+package org.tigris.scarab.om;
+
+
+import org.apache.torque.TorqueException;
+import org.apache.torque.om.Persistent;
+
+/**
+ * Notification rule table to determine when a notification has to be sent out to whom. Used by NotificationManager.
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+public class NotificationRule
+ extends org.tigris.scarab.om.BaseNotificationRule
+ implements Persistent
+{
+
+ /**
+ * Create a default filter.
+ *
+ * @param moduleId
+ * @param userId
+ * @param managerId
+ * @param activityType
+ * @return
+ * @throws TorqueException
+ */
+ public static NotificationRule createDefaultRule(Integer moduleId,
+ Integer userId,
+ Integer managerId,
+ String activityType) throws TorqueException
+ {
+ NotificationRule rule = new NotificationRule();
+ rule.setModuleId(moduleId);
+ rule.setUserId(userId);
+ rule.setActivityType(activityType);
+ rule.setManagerId(managerId);
+
+ // default settings.
+ // currently hard coded. will later be
+ // replaced by a default customization
+
+ rule.setFilterState(true); // enabled by default
+ rule.setSendSelf(false); // don't send to myself by default
+ rule.setSendFailures(false); // don't notify me about failures by default
+ rule.save();
+ return rule;
+ }
+
+}
Added: trunk/src/java/org/tigris/scarab/om/NotificationRuleManager.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/NotificationRuleManager.java?view=markup&pathrev763
=============================================================================--- (empty file)
+++ trunk/src/java/org/tigris/scarab/om/NotificationRuleManager.java 2009-06-27 07:44:10-0700
@@ -0,0 +1,133 @@
+
+package org.tigris.scarab.om;
+
+import java.util.List;
+
+import org.apache.torque.TorqueException;
+import org.apache.torque.util.Criteria;
+import org.tigris.scarab.notification.ActivityType;
+import org.tigris.scarab.notification.Notification;
+import org.tigris.scarab.notification.NotificationManagerFactory;
+import org.tigris.scarab.tools.localization.L10NKeySet;
+import org.tigris.scarab.util.ScarabException;
+
+/**
+ * This class manages NotificationRule objects.
+ *
+ * Notification rule table to determine when a notification has to be sent out to whom. Used by NotificationManager.
+ *
+ * The skeleton for this class was autogenerated by Torque * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+public class NotificationRuleManager
+ extends org.tigris.scarab.om.BaseNotificationRuleManager
+{
+ /**
+ * Creates a new <code>NotificationRuleManager</code> instance.
+ *
+ * @exception TorqueException if an error occurs
+ */
+ public NotificationRuleManager()
+ throws TorqueException
+ {
+ super();
+ }
+ public static NotificationRule getNotificationRule(NotificationStatus notif) throws ScarabException
+ {
+ NotificationRule rule = null;
+ try
+ {
+ Long issueId = notif.getIssueId();
+ Issue issue = IssueManager.getInstance(issueId);
+ Integer moduleId = issue.getModuleId();
+ Integer userId = notif.getReceiverId();
+ ActivityType activityType = notif.getActivityType();
+ rule = getNotificationRule(moduleId, userId, activityType.getCode());
+ }
+ catch(TorqueException te)
+ {
+ throw new ScarabException(L10NKeySet.ExceptionTorqueGeneric, te);
+ }
+ return rule;
+ }
+
+ public static NotificationRule getNotificationRule(Integer moduleId, Integer userId, String activityType) throws ScarabException
+ {
+ NotificationRule rule = null;
+
+ int managerId = NotificationManagerFactory.getInstance().getManagerId();
+ Criteria crit = new Criteria();
+ crit.add(NotificationRulePeer.USER_ID, userId);
+ crit.add(NotificationRulePeer.MODULE_ID, moduleId);
+ crit.add(NotificationRulePeer.ACTIVITY_TYPE, activityType);
+ crit.add(NotificationRulePeer.MANAGER_ID, managerId);
+
+ try
+ {
+ List<NotificationRule> ruleSet = (List<NotificationRule>)NotificationRulePeer.doSelect(crit);
+ if(ruleSet == null || ruleSet.size()==0)
+ {
+
+ rule = NotificationRule.createDefaultRule(
+ moduleId,
+ userId,
+ managerId,
+ activityType);
+ }
+ else if (ruleSet.size() > 1)
+ {
+ String msg = "Database inxonsistency:"
+ + " Expected at most one key matching (user_id,module_id,activity_type,manager_id) = "
+ + ")" + userId + "," + moduleId + "," + activityType + "," + managerId + ")";
+ throw new TorqueException(msg,new Throwable());
+ }
+ else
+ {
+ rule = ruleSet.get(0);
+ }
+ }
+ catch(TorqueException te)
+ {
+ throw new ScarabException(L10NKeySet.ExceptionTorqueGeneric,te);
+ }
+
+ return rule;
+ }
+
+ /**
+ * determines whether user has enabled notifications for given activityType
+ * in given module.
+ * @param user
+ * @param act
+ * @return
+ * @throws ScarabException
+ * @throws TorqueException
+ */
+ public static boolean isNotificationEnabledFor(ScarabUser user, Issue issue, boolean isSelf, String activityType) throws ScarabException, TorqueException
+ {
+ Integer userId = user.getUserId();
+ Module module = issue.getModule();
+ Integer moduleId = module.getModuleId();
+
+ NotificationRule rule = getNotificationRule(moduleId, userId, activityType);
+ boolean isEnabled;
+ if(isSelf)
+ {
+ isEnabled = rule.getSendSelf();
+ }
+ else
+ {
+ isEnabled = rule.getFilterState();
+ }
+
+ if(isEnabled)
+ {
+ Notification notification = new Notification(user, issue);
+ isEnabled = notification.sendConditionsMatch();
+ }
+ return isEnabled;
+ }
+
+
+}
Added: trunk/src/java/org/tigris/scarab/om/NotificationRulePeer.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/NotificationRulePeer.java?view=markup&pathrev763
=============================================================================--- (empty file)
+++ trunk/src/java/org/tigris/scarab/om/NotificationRulePeer.java 2009-06-27 07:44:10-0700
@@ -0,0 +1,164 @@
+package org.tigris.scarab.om;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.torque.TorqueException;
+import org.apache.torque.util.Criteria;
+import org.tigris.scarab.notification.ActivityType;
+import org.tigris.scarab.notification.Notification;
+
+/**
+ * Notification rule table to determine when a notification has to be sent out to whom. Used by NotificationManager.
+ *
+ * You should add additional methods to this class to meet the
+ * application requirements. This class will only be generated as
+ * long as it does not already exist in the output directory.
+ */
+public class NotificationRulePeer
+ extends org.tigris.scarab.om.BaseNotificationRulePeer
+{
+
+ /**
+ * Return the list of configured managers for this user, this module
+ * and this activityType.
+ * NOTE: Currently only the Scarab default Notification manager is
+ * supported, so the List will mostly contain 1 element. It is planned
+ * to add more managers in the future, so be prepared to find multiple
+ * entries in the List.
+ * If no manager is configured, return an empty List
+ * @param moduleId
+ * @param userId
+ * @param activityType
+ * @return
+ * @throws TorqueException
+ */
+ static public List<NotificationRule> getCustomization(Object moduleId, Object userId, Object activityType) throws TorqueException
+ {
+ List<NotificationRule> entries = null;
+ Criteria crit = new Criteria();
+ crit.add(MODULE_ID, moduleId, Criteria.EQUAL);
+ crit.add(USER_ID, userId, Criteria.EQUAL);
+ crit.add(ACTIVITY_TYPE, activityType, Criteria.EQUAL);
+ try {
+ entries = (List<NotificationRule>)doSelect(crit);
+ } catch (TorqueException e) {
+ log.error("getPendingNotifications(): " + e);
+ }
+ /*
+ if(entries.size()==0)
+ {
+ NotificationRule rule =
+ NotificationRule.createDefaultRule(
+ (Integer)moduleId,
+ (Integer)userId,
+ NotificationManagerFactory.getInstance().getManagerId(),
+ ActivityType.getActivityType((String)activityType));
+ }
+ */
+ return entries;
+ }
+
+ static public Map<String,List<NotificationRule>> getCustomization(Object moduleId, Object userId) throws TorqueException
+ {
+ Map<String,List<NotificationRule>> entries = new Hashtable<String,List<NotificationRule>>();
+ Set<String> codes = (Set<String>)ActivityType.getActivityTypeCodes();
+ Iterator<String> iter = codes.iterator();
+ while(iter.hasNext())
+ {
+ String code = (String)iter.next();
+ List<NotificationRule> items = getCustomization(moduleId, userId, code);
+ entries.put(code,items);
+ }
+ return entries;
+ }
+
+ static public List<NotificationRule> getNotificationRules(ScarabUser user, Module module) throws TorqueException
+ {
+ List<NotificationRule> entries = new ArrayList<NotificationRule>();
+ Set<String> codes = (Set<String>)ActivityType.getActivityTypeCodes();
+ Iterator<String> iter = codes.iterator();
+ Integer moduleId = module.getModuleId();
+ Integer userId = user.getUserId();
+ while(iter.hasNext())
+ {
+ String code = (String)iter.next();
+ List<NotificationRule> items = getCustomization(moduleId, userId, code);
+ if(items != null && items.size()>0)
+ entries.add(items.get(0));
+ }
+ return entries;
+ }
+
+ /**
+ * UpLoad the User Notification options' IDs from the template combo.
+ * @param aOptionId
+ * @throws TorqueException
+ */
+ public static void saveConditions(ScarabUser user, Module module, Integer[] aOptionId, Integer operator) throws TorqueException
+ {
+ deleteConditions(user, module);
+ ConditionManager.clear();
+ if (aOptionId != null)
+ for (int i=0; i<aOptionId.length; i++)
+ {
+ if (aOptionId[i].intValue() != 0)
+ {
+ Condition cond = new Condition();
+ cond.setAttributeId(null);
+ cond.setOptionId(aOptionId[i]);
+ cond.setModuleId(module.getModuleId());
+ cond.setIssueTypeId(null);
+ cond.setTransitionId(null);
+ cond.setUserId(user.getUserId());
+ cond.setOperator(operator);
+ cond.save();
+ }
+ }
+ }
+
+ /**
+ * Returns the list of conditions associated for the given user/module
+ * combination. Used with NotificationManager.
+ * @param user
+ * @param module
+ * @return
+ * @throws TorqueException
+ */
+ public static List<Condition> getConditions(ScarabUser user, Module module) throws TorqueException
+ {
+ List<Condition> result = null;
+ Criteria crit = new Criteria();
+ crit.add(ConditionPeer.USER_ID, user.getUserId());
+ crit.add(ConditionPeer.MODULE_ID, module.getModuleId());
+ result = (List<Condition>)ConditionPeer.doSelect(crit);
+ return result;
+ }
+
+ public static Notification getEmptyNotificationFor(ScarabUser user, Module module) throws TorqueException
+ {
+ Notification notification = null;
+ return notification;
+
+ }
+
+ public static void deleteConditions(ScarabUser user, Module module) throws TorqueException
+ {
+ Criteria crit = new Criteria();
+ crit.add(ConditionPeer.ATTRIBUTE_ID, null);
+ crit.add(ConditionPeer.MODULE_ID, module.getModuleId());
+ crit.add(ConditionPeer.ISSUE_TYPE_ID, null);
+ crit.add(ConditionPeer.TRANSITION_ID, null);
+ crit.add(ConditionPeer.USER_ID, user.getUserId());
+ ConditionPeer.doDelete(crit);
+ }
+
+ public static List<AttributeOption> getSelectedAttributeOptionsForNotification(ScarabUser user, Module module)
+ {
+ return null;
+ }
+}
Modified: trunk/src/java/org/tigris/scarab/om/RModuleAttribute.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/RModuleAttribute.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/RModuleAttribute.java (original)
+++ trunk/src/java/org/tigris/scarab/om/RModuleAttribute.java 2009-06-27 07:44:10-0700
@@ -55,6 +55,7 @@
import org.apache.torque.TorqueException;
import org.apache.torque.om.Persistent;
import org.apache.torque.util.Criteria;
+import org.apache.torque.util.UniqueList;
import org.apache.fulcrum.localization.Localization;
import org.tigris.scarab.services.cache.ScarabCache;
@@ -263,25 +264,70 @@
private static List getRMAs(Integer moduleId, Integer issueTypeId)
- throws TorqueException
+ throws TorqueException
+{
+ List result = null;
+ Object obj = ScarabCache.get(R_MODULE_ATTTRIBUTE, GET_RMAS,
+ moduleId, issueTypeId);
+ if (obj == null)
+ {
+ Criteria crit = new Criteria()
+ .add(RModuleAttributePeer.MODULE_ID, moduleId)
+ .add(RModuleAttributePeer.ISSUE_TYPE_ID, issueTypeId);
+ crit.addAscendingOrderByColumn(
+ RModuleAttributePeer.PREFERRED_ORDER);
+ result = RModuleAttributePeer.doSelect(crit);
+ ScarabCache.put(result, R_MODULE_ATTTRIBUTE, GET_RMAS,
+ moduleId, issueTypeId);
+ }
+ else
{
- List result = null;
- Object obj = ScarabCache.get(R_MODULE_ATTTRIBUTE, GET_RMAS,
- moduleId, issueTypeId);
- if (obj == null)
- {
- Criteria crit = new Criteria()
- .add(RModuleAttributePeer.MODULE_ID, moduleId)
- .add(RModuleAttributePeer.ISSUE_TYPE_ID, issueTypeId);
- crit.addAscendingOrderByColumn(
- RModuleAttributePeer.PREFERRED_ORDER);
- result = RModuleAttributePeer.doSelect(crit);
- ScarabCache.put(result, R_MODULE_ATTTRIBUTE, GET_RMAS,
- moduleId, issueTypeId);
- }
- else
+ result = (List)obj;
+ }
+ return result;
+}
+
+ /**
+ * Return the set of rma's for the module (not only for the issue type)
+ **/
+ private static List<RModuleAttribute> getRMAs(Integer moduleId)
+ throws TorqueException
+{
+ List<RModuleAttribute> result = null;
+ Object obj = ScarabCache.get(R_MODULE_ATTTRIBUTE, GET_RMAS, moduleId);
+ if (obj == null)
+ {
+ Criteria crit = new Criteria()
+ .add(RModuleAttributePeer.MODULE_ID, moduleId);
+ crit.addAscendingOrderByColumn(
+ RModuleAttributePeer.PREFERRED_ORDER);
+ result = (List<RModuleAttribute>)RModuleAttributePeer.doSelect(crit);
+ ScarabCache.put(result, R_MODULE_ATTTRIBUTE, GET_RMAS,
+ moduleId);
+ }
+ else
+ {
+ result = (List<RModuleAttribute>)obj;
+ }
+ return result;
+}
+
+ /**
+ * Return the list of RModuleAttribute IDs which are defined for the current module.
+ * @param moduleId
+ * @return
+ * @throws TorqueException
+ */
+ public static List<Integer> getRMAIds(Integer moduleId)
+ throws TorqueException
+ {
+ List<RModuleAttribute> rmas = getRMAs(moduleId);
+ Iterator<RModuleAttribute> iter = rmas.iterator();
+ List<Integer> result = new ArrayList();
+ while(iter.hasNext())
{
- result = (List)obj;
+ RModuleAttribute rma = iter.next();
+ result.add(rma.getAttributeId());
}
return result;
}
@@ -370,7 +416,28 @@
setDefaultTextFlag(b);
}
- public List getConditions() throws TorqueException
+ /**
+ * Return the boolean operator to be used to combine different attributes.
+ * @return
+ */
+ public Integer getConditionOperator()
+ {
+ Integer operator = 0;
+ List<Condition> conditions;
+ try {
+ conditions = getConditions();
+ } catch (TorqueException e) {
+ // TODO Auto-generated catch block
+ throw new RuntimeException(e);
+ }
+ if(conditions.size() > 0)
+ {
+ operator = conditions.get(0).getOperator();
+ }
+ return operator;
+ }
+
+ public List<Condition> getConditions() throws TorqueException
{
if (collConditions == null)
{
@@ -414,7 +481,7 @@
* @param aOptionId
* @throws TorqueException
*/
- public void setConditionsArray(Integer aOptionId[]) throws TorqueException
+ public void setConditionsArray(Integer aOptionId[], Integer operator) throws TorqueException
{
Criteria crit = new Criteria();
crit.add(ConditionPeer.ATTRIBUTE_ID, this.getAttributeId());
@@ -436,6 +503,7 @@
cond.setTransitionId(null);
cond.setIssueTypeId(this.getIssueTypeId());
cond.setModuleId(this.getModuleId());
+ cond.setOperator(operator);
this.addCondition(cond);
cond.save();
}
Modified: trunk/src/java/org/tigris/scarab/om/RModuleIssueType.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/RModuleIssueType.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/RModuleIssueType.java (original)
+++ trunk/src/java/org/tigris/scarab/om/RModuleIssueType.java 2009-06-27 07:44:10-0700
@@ -310,7 +310,7 @@
* SCARAB_R_MODULE_ATTRIBUTE's records)
*
*/
- public List getConditions(Criteria criteria) throws TorqueException
+ public List<Condition> getConditions(Criteria criteria) throws TorqueException
{
criteria.add(ConditionPeer.ATTRIBUTE_ID, (Object)(ConditionPeer.ATTRIBUTE_ID + " IS NULL"), Criteria.CUSTOM);
return super.getConditions(criteria);
@@ -321,7 +321,7 @@
*/
public Integer[] getConditionsArray()
{
- List conditions = new ArrayList();
+ List conditions = new ArrayList<Condition>();
Integer[] aIDs = null;
try
{
@@ -329,9 +329,11 @@
conditions = this.getConditions();
aIDs = new Integer[conditions.size()];
int i=0;
- for (Iterator iter = conditions.iterator(); iter.hasNext(); i++)
+ for (Iterator<Condition> iter = conditions.iterator(); iter.hasNext(); i++)
{
- aIDs[i] = (Integer)iter.next();
+ Condition condition = iter.next();
+ long id = condition.getConditionId();
+ aIDs[i] = (int)id;
}
}
catch (TorqueException e)
@@ -341,10 +343,33 @@
return aIDs;
}
+ /**
+ * Return the boolean operator to be used to combine different attributes.
+ * @return
+ */
+ public Integer getConditionOperator()
+ {
+ Integer operator = 0;
+ List<Condition> conditions;
+ try {
+ conditions = getConditions();
+ } catch (TorqueException e) {
+ // TODO Auto-generated catch block
+ throw new RuntimeException(e);
+ }
+ if(conditions.size() > 0)
+ {
+ operator = conditions.get(0).getOperator();
+ }
+ return operator;
+ }
+
+
+
/* (non-Javadoc)
* @see org.tigris.scarab.om.Conditioned#setConditionsArray(java.lang.Integer[])
*/
- public void setConditionsArray(Integer[] aOptionId) throws TorqueException
+ public void setConditionsArray(Integer[] aOptionId, Integer operator) throws TorqueException
{
Criteria crit = new Criteria();
crit.add(ConditionPeer.ATTRIBUTE_ID, null);
@@ -366,6 +391,7 @@
cond.setModuleId(this.getModuleId());
cond.setIssueTypeId(this.getIssueTypeId());
cond.setTransitionId(null);
+ cond.setOperator(operator);
this.addCondition(cond);
cond.save();
}
Modified: trunk/src/java/org/tigris/scarab/om/RModuleOption.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/RModuleOption.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/RModuleOption.java (original)
+++ trunk/src/java/org/tigris/scarab/om/RModuleOption.java 2009-06-27 07:44:10-0700
@@ -48,6 +48,7 @@
// JDK classes
import java.util.Comparator;
+import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.sql.Connection;
@@ -60,6 +61,7 @@
import org.tigris.scarab.om.ModuleManager;
import org.tigris.scarab.om.Module;
+import org.tigris.scarab.services.cache.ScarabCache;
import org.tigris.scarab.tools.localization.L10NKeySet;
import org.tigris.scarab.util.ScarabException;
import org.tigris.scarab.workflow.WorkflowFactory;
@@ -75,6 +77,11 @@
implements Persistent
{
+ private static final String R_MODULE_OPTION =
+ "RModuleOption";
+ private static final String GET_RMOS =
+ "getRMOs";
+
private int level;
private static final Comparator COMPARATOR = new Comparator()
@@ -333,4 +340,41 @@
}
}
}
+
+ public static List<Integer> getRMOIds(Integer moduleId) throws TorqueException
+ {
+ List<RModuleOption> rmos = getRMOs(moduleId);
+ Iterator<RModuleOption> iter = rmos.iterator();
+ List<Integer> result = new ArrayList();
+ while(iter.hasNext())
+ {
+ RModuleOption rmo = iter.next();
+ result.add(rmo.getOptionId());
+ }
+ return result;
+ }
+
+ public static List<RModuleOption> getRMOs(Integer moduleId)
+ throws TorqueException
+{
+ List<RModuleOption> result = null;
+ Object obj = ScarabCache.get(R_MODULE_OPTION, GET_RMOS, moduleId);
+ if (obj == null)
+ {
+ Criteria crit = new Criteria()
+ .add(RModuleOptionPeer.MODULE_ID, moduleId);
+ crit.addAscendingOrderByColumn(
+ RModuleOptionPeer.PREFERRED_ORDER);
+ result = (List<RModuleOption>)RModuleOptionPeer.doSelect(crit);
+ ScarabCache.put(result, R_MODULE_OPTION, GET_RMOS,
+ moduleId);
+ }
+ else
+ {
+ result = (List<RModuleOption>)obj;
+ }
+ return result;
+}
+
+
}
Modified: trunk/src/java/org/tigris/scarab/om/ScarabModule.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/ScarabModule.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/ScarabModule.java (original)
+++ trunk/src/java/org/tigris/scarab/om/ScarabModule.java 2009-06-27 07:44:10-0700
@@ -50,10 +50,13 @@
import com.workingdogs.village.DataSetException;
import java.io.Serializable;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Set;
+import java.util.StringTokenizer;
// Commons classes
import org.apache.commons.lang.StringUtils;
@@ -77,6 +80,7 @@
import org.tigris.scarab.om.Module;
import org.tigris.scarab.om.MITList;
import org.tigris.scarab.om.ScarabUserManager;
+import org.tigris.scarab.tools.ScarabUserTool;
import org.tigris.scarab.tools.localization.L10NKey;
import org.tigris.scarab.tools.localization.L10NKeySet;
import org.tigris.scarab.util.ScarabConstants;
@@ -965,7 +969,68 @@
return email;
}
-
+
+ /**
+ * Examines the modules archiveEmail string (which may contain multiple
+ * email targets) and returns only those entries, which are recognized as
+ * local ScarabUsers.
+ * Note: archiving ScarabUsers need to be specified by their exact username
+ * as known in Scarab.
+ * This method returns a set of ScarabUser instances.
+ */
+ public Set<ScarabUser> getArchivingScarabUsers()
+ {
+ Set<ScarabUser> expandedArchiveAddresses = new HashSet<ScarabUser>();
+
+ String archiveAddresses = getArchiveEmail();
+ if(archiveAddresses!=null)
+ {
+ StringTokenizer st = new StringTokenizer(archiveAddresses, ",;");
+ while (st.hasMoreTokens())
+ {
+ String userName = st.nextToken().trim();
+ ScarabUser user = ScarabUserTool.getUserByUserName(userName);
+ if(user != null)
+ {
+ expandedArchiveAddresses.add(user);
+ }
+ }
+ }
+ return expandedArchiveAddresses;
+ }
+
+
+ /**
+ * Examines the modules archiveEmail string (which may contain multiple
+ * email targets) and returns only those entries, which are NOT recognized as
+ * local ScarabUsers, hence interpreted as foreign Email Addresses.
+ * Note: archivingMailAdresses must be valid EmailAdresses!
+ * This method returns a set of Strings containing Email Addresses
+ */
+ public Set<String> getArchivingMailAddresses()
+ {
+ Set<String> expandedArchiveAddresses = new HashSet();
+
+ String archiveAddresses = getArchiveEmail();
+ if(archiveAddresses!=null)
+ {
+ StringTokenizer st = new StringTokenizer(archiveAddresses, ",;");
+ while (st.hasMoreTokens())
+ {
+ String userName = st.nextToken().trim();
+ ScarabUser user = ScarabUserTool.getUserByUserName(userName);
+ if(user == null)
+ {
+ expandedArchiveAddresses.add(userName);
+ }
+ }
+ }
+ return expandedArchiveAddresses;
+ }
+
+
+
+
/**
* returns an array of Roles that can be approved without need for
* moderation.
Modified: trunk/src/java/org/tigris/scarab/om/Transition.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Transition.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/om/Transition.java (original)
+++ trunk/src/java/org/tigris/scarab/om/Transition.java 2009-06-27 07:44:10-0700
@@ -204,9 +204,9 @@
/**
* Returns the conditions associated to this Transition
*/
- public List getConditions() throws TorqueException
+ public List<Condition> getConditions() throws TorqueException
{
- List conds = (List)TransitionManager.getMethodResult().get(this, "getConditions");
+ List<Condition> conds = (List<Condition>)TransitionManager.getMethodResult().get(this, "getConditions");
if (conds == null)
{
conds = super.getConditions();
@@ -222,7 +222,7 @@
*/
public Integer[] getConditionsArray()
{
- List conditions = new ArrayList();
+ List<Condition> conditions = new ArrayList<Condition>();
Integer[] aIDs = null;
try
{
@@ -230,9 +230,11 @@
conditions = this.getConditions();
aIDs = new Integer[conditions.size()];
int i=0;
- for (Iterator iter = conditions.iterator(); iter.hasNext(); i++)
+ for (Iterator<Condition> iter = conditions.iterator(); iter.hasNext(); i++)
{
- aIDs[i] = (Integer)iter.next();
+ Condition condition = iter.next();
+ long id = condition.getConditionId();
+ aIDs[i] = (int)id;
}
}
catch (TorqueException e)
@@ -241,12 +243,35 @@
}
return aIDs;
}
+
+ /**
+ * Return the boolean operator to be used to combine different attributes.
+ * @return
+ */
+ public Integer getConditionOperator()
+ {
+ Integer operator = 0;
+ List<Condition> conditions;
+ try {
+ conditions = getConditions();
+ } catch (TorqueException e) {
+ // TODO Auto-generated catch block
+ throw new RuntimeException(e);
+ }
+ if(conditions.size() > 0)
+ {
+ operator = conditions.get(0).getOperator();
+ }
+ return operator;
+ }
+
+
/**
* Load the attribute options' IDs from the template combo.
* @param aOptionId
* @throws TorqueException
*/
- public void setConditionsArray(Integer aOptionId[]) throws TorqueException
+ public void setConditionsArray(Integer aOptionId[], Integer operator) throws TorqueException
{
Criteria crit = new Criteria();
crit.add(ConditionPeer.ATTRIBUTE_ID, null);
@@ -268,6 +293,7 @@
cond.setAttributeId(null);
cond.setModuleId(null);
cond.setIssueTypeId(null);
+ cond.setOperator(operator);
this.addCondition(cond);
cond.save();
}
Modified: trunk/src/java/org/tigris/scarab/tools/ScarabGlobalTool.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/tools/ScarabGlobalTool.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/tools/ScarabGlobalTool.java (original)
+++ trunk/src/java/org/tigris/scarab/tools/ScarabGlobalTool.java 2009-06-27 07:44:10-0700
@@ -76,12 +76,14 @@
import org.radeox.engine.context.BaseRenderContext;
import org.tigris.scarab.notification.ActivityType;
+import org.tigris.scarab.notification.Notification;
import org.tigris.scarab.om.AttributePeer;
import org.tigris.scarab.om.IssueTypePeer;
-import org.tigris.scarab.om.NotificationFilter;
-import org.tigris.scarab.om.NotificationFilterManager;
-import org.tigris.scarab.om.NotificationFilterPeer;
+import org.tigris.scarab.om.NotificationRule;
+import org.tigris.scarab.om.NotificationRuleManager;
+import org.tigris.scarab.om.NotificationRulePeer;
+import org.tigris.scarab.om.ScarabModule;
import org.tigris.scarab.om.ScarabUser;
import org.tigris.scarab.om.ScarabUserImplPeer;
import org.tigris.scarab.om.GlobalParameterManager;
@@ -367,7 +369,7 @@
/**
- * Return the list of available NotificationFilters for
+ * Return the list of available NotificationRules for
* the given user in the given module
* @param moduleId
* @param userId
@@ -377,15 +379,32 @@
*/
public List getCustomization(Object moduleId, Object userId, Object activityCode) throws TorqueException
{
- NotificationFilterPeer nfp = new NotificationFilterPeer();
+ NotificationRulePeer nfp = new NotificationRulePeer();
List result = nfp.getCustomization(moduleId, userId, activityCode);
return result;
}
+ public static Notification getEmptyNotificationFor(ScarabUser user, ScarabModule module) throws TorqueException
+ {
+ return new Notification(user, module);
+ }
- public static NotificationFilter getNotificationFilter(Integer moduleId, Integer userId, String activityCode) throws ScarabException
+ public static NotificationRule getNotificationRule(Integer moduleId, Integer userId, String activityCode) throws ScarabException
+ {
+ NotificationRule result = NotificationRuleManager.getNotificationRule(moduleId, userId, activityCode);
+ return result;
+ }
+
+ /**
+ * Return the NotificationRule with the given RuleId.
+ * This method has mainly been created for ConditionEdit.vm
+ * @param ruleId
+ * @return
+ * @throws TorqueException
+ */
+ public static NotificationRule getNotificationRule(Integer ruleId) throws TorqueException
{
- NotificationFilter result = NotificationFilterManager.getNotificationFilter(moduleId, userId, activityCode);
+ NotificationRule result = NotificationRuleManager.getInstance(ruleId);
return result;
}
Modified: trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java (original)
+++ trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java 2009-06-27 07:44:10-0700
@@ -501,60 +501,20 @@
* You can pass in either a Integer or something that
* will resolve to a String object as id.toString() is
* called on everything that isn't a Integer.
+ * @deprecated use ScarabUserTool.getUser(Object userId)
*/
- public ScarabUser getUser(Object userId)
- throws TorqueException
+ public ScarabUser getUser(Object userId) throws TorqueException
{
- if (userId == null)
- {
- return null;
- }
-
- if(IssueSearch.SEARCHING_USER_KEY.equalsIgnoreCase(userId.toString()))
- {
- return IssueSearch.getSearchingUserPlaceholder();
- }
-
- Integer pk = null;
- try
- {
- pk = new Integer(userId.toString());
- }
- catch( NumberFormatException e)
- {
- return null;
- }
-
- ScarabUser su = null;
- try
- {
- su = ScarabUserManager.getInstance(pk);
- }
- catch (TorqueException e)
- {
- return null;
- }
- return su;
+ return ScarabUserTool.getUser(userId);
}
/**
* Return a specific User by username.
+ * @deprecated Use ScarabUserTool.getUserByUserName(String username)
*/
- public ScarabUser getUserByUserName(String username)
- throws Exception
+ public ScarabUser getUserByUserName(String username)
{
- ScarabUser su = null;
- try
- {
- su = ScarabUserManager.getInstance(username);
- }
- catch (Exception e)
- {
- // Logged at debug level, as a null user is interpreted
- // as an invalid username
- Log.get().debug("User, "+username+" could not be found,", e);
- }
- return su;
+ return ScarabUserTool.getUserByUserName(username);
}
/**
@@ -1166,7 +1126,6 @@
* @return a <code>Module</code> value
*/
public Module getModule()
- throws Exception
{
try
{
@@ -2398,29 +2357,7 @@
*/
public List sortUsers(List userList) throws Exception
{
- final String sortColumn = data.getParameters().getString("sortColumn");
- final String sortPolarity = data.getParameters().getString("sortPolarity");
- final int polarity = ("desc".equals(sortPolarity)) ? -1 : 1;
- Comparator c = new Comparator()
- {
- public int compare(Object o1, Object o2)
- {
- int i = 0;
- if ("username".equals(sortColumn))
- {
- i = polarity * ((ScarabUser)o1).getUserName()
- .compareTo(((ScarabUser)o2).getUserName());
- }
- else
- {
- i = polarity * ((ScarabUser)o1).getName()
- .compareTo(((ScarabUser)o2).getName());
- }
- return i;
- }
- };
- Collections.sort(userList, c);
- return userList;
+ return ScarabUserTool.sortUsers(userList, data);
}
@@ -3127,6 +3064,11 @@
{
return AttributeOptionPeer.getSortedAttributeOptions();
}
+
+ public List getSortedAttributeOptionsForModule(Module module) throws TorqueException
+ {
+ return AttributeOptionPeer.getSortedAttributeOptions(module);
+ }
/**
* Returned all attribute options allowed for every attribute assigned to this
@@ -3149,12 +3091,12 @@
}
/**
* Returns if the system is configurated to allow anonymous login.
- *
+ * @deprecated use ScarabUserTool.isAnonymousLoginAllowed()
*/
public boolean isAnonymousLoginAllowed()
throws TorqueException
{
- return ScarabUserManager.anonymousAccessAllowed();
+ return ScarabUserTool.isAnonymousLoginAllowed();
}
public Transition getTransition(Integer pk)
Added: trunk/src/java/org/tigris/scarab/tools/ScarabUserTool.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/tools/ScarabUserTool.java?view=markup&pathrev763
=============================================================================--- (empty file)
+++ trunk/src/java/org/tigris/scarab/tools/ScarabUserTool.java 2009-06-27 07:44:10-0700
@@ -0,0 +1,119 @@
+package org.tigris.scarab.tools;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.torque.TorqueException;
+import org.apache.turbine.RunData;
+import org.tigris.scarab.om.ScarabUser;
+import org.tigris.scarab.om.ScarabUserManager;
+import org.tigris.scarab.util.Log;
+import org.tigris.scarab.util.word.IssueSearch;
+
+public class ScarabUserTool
+{
+
+ /**
+ * Return a specific User by username.
+ */
+ public static ScarabUser getUserByUserName(String username)
+ {
+ ScarabUser su = null;
+ try
+ {
+ su = ScarabUserManager.getInstance(username);
+ }
+ catch (Exception e)
+ {
+ // Logged at debug level, as a null user is interpreted
+ // as an invalid user name
+ Log.get().debug("User, "+username+" could not be found,", e);
+ }
+ return su;
+ }
+
+ /**
+ * Return a specific User by ID from within the system.
+ * You can pass in either a Integer or something that
+ * will resolve to a String object as id.toString() is
+ * called on everything that isn't a Integer.
+ */
+ public static ScarabUser getUser(Object userId)
+ throws TorqueException
+ {
+ if (userId == null)
+ {
+ return null;
+ }
+
+ if(IssueSearch.SEARCHING_USER_KEY.equalsIgnoreCase(userId.toString()))
+ {
+ return IssueSearch.getSearchingUserPlaceholder();
+ }
+
+ Integer pk = null;
+ try
+ {
+ pk = new Integer(userId.toString());
+ }
+ catch( NumberFormatException e)
+ {
+ return null;
+ }
+
+ ScarabUser su = null;
+ try
+ {
+ su = ScarabUserManager.getInstance(pk);
+ }
+ catch (TorqueException e)
+ {
+ return null;
+ }
+ return su;
+ }
+
+ /**
+ * Sort users on name or email.
+ */
+ public static List sortUsers(List userList, RunData data) throws Exception
+ {
+ final String sortColumn = data.getParameters().getString("sortColumn");
+ final String sortPolarity = data.getParameters().getString("sortPolarity");
+ final int polarity = ("desc".equals(sortPolarity)) ? -1 : 1;
+ Comparator c = new Comparator()
+ {
+ public int compare(Object o1, Object o2)
+ {
+ int i = 0;
+ if ("username".equals(sortColumn))
+ {
+ i = polarity * ((ScarabUser)o1).getUserName()
+ .compareTo(((ScarabUser)o2).getUserName());
+ }
+ else
+ {
+ i = polarity * ((ScarabUser)o1).getName()
+ .compareTo(((ScarabUser)o2).getName());
+ }
+ return i;
+ }
+ };
+ Collections.sort(userList, c);
+ return userList;
+ }
+
+
+ /**
+ * Returns if the system is configurated to allow anonymous login.
+ *
+ */
+ public static boolean isAnonymousLoginAllowed()
+ throws TorqueException
+ {
+ return ScarabUserManager.anonymousAccessAllowed();
+ }
+
+
+}
Modified: trunk/src/java/org/tigris/scarab/util/Email.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/Email.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/util/Email.java (original)
+++ trunk/src/java/org/tigris/scarab/util/Email.java 2009-06-27 07:44:10-0700
@@ -382,22 +382,6 @@
return archiveUser;
}
- /**
- * returns the archive Email addresses of a module
- */
- private static Set getArchiveAddresses(Module module)
- {
- Set expandedArchiveAddresses = new HashSet();
-
- String archiveAddresses = module.getArchiveEmail();
- if(archiveAddresses!=null)
- {
- StringTokenizer st = new StringTokenizer(archiveAddresses, ",;");
- while (st.hasMoreTokens())
- expandedArchiveAddresses.add(st.nextToken().trim());
- }
- return expandedArchiveAddresses;
- }
private static void fileUser(Map userLocaleMap, ScarabUser user,
Module module, int toOrCC) throws Exception
@@ -406,10 +390,11 @@
{
fileAddress(userLocaleMap, new InternetAddress(user.getEmail(),
user.getName()), chooseLocale(user, module), toOrCC);
- }
+ }
else
{
- for(Iterator addresses=getArchiveAddresses(module).iterator();addresses.hasNext();)
+ Set<String> archivingMailAddresses = module.getArchivingMailAddresses();
+ for(Iterator<String> addresses= archivingMailAddresses.iterator();addresses.hasNext();)
{
fileAddress(userLocaleMap, new InternetAddress((String)addresses.next(),
user.getName()), chooseLocale(user, module), toOrCC);
Modified: trunk/src/java/org/tigris/scarab/util/ScarabConstants.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/ScarabConstants.java?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/java/org/tigris/scarab/util/ScarabConstants.java (original)
+++ trunk/src/java/org/tigris/scarab/util/ScarabConstants.java 2009-06-27 07:44:10-0700
@@ -115,9 +115,10 @@
final String ID = "id";
/**
- * Primary System Object
+ * Primary System Objects
*/
final String SCARAB_REQUEST_TOOL = "scarabR";
+ final String SCARAB_USER_TOOL = "scarabU";
/**
* Name of the scarab Link Tool
@@ -333,11 +334,12 @@
public static final String HTTP_PORT = "scarab.http.port";
// Condition editor constants
- public static int TRANSITION_OBJECT = 0;
- public static int GLOBAL_ATTRIBUTE_OBJECT = 1;
- public static int MODULE_ATTRIBUTE_OBJECT = 2;
+ public static int TRANSITION_OBJECT = 0;
+ public static int GLOBAL_ATTRIBUTE_OBJECT = 1;
+ public static int MODULE_ATTRIBUTE_OBJECT = 2;
public static int BLOCKED_MODULE_ISSUE_TYPE_OBJECT = 3;
+ public static int NOTIFICATION_ATTRIBUTE_OBJECT = 4;
public static String IS_BLOCKED = "IsBlocked";
- public static String BLOCKS = "Blocks";
+ public static String BLOCKS = "Blocks";
}
Modified: trunk/src/schema/scarab-schema.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/schema/scarab-schema.xml?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/schema/scarab-schema.xml (original)
+++ trunk/src/schema/scarab-schema.xml 2009-06-27 07:44:10-0700
@@ -152,13 +152,15 @@
<reference local="CREATED_BY" foreign="USER_ID"/>
</foreign-key>
</table>
- <table name="SCARAB_CONDITION" idMethod="idbroker" javaName="Condition">
- <column name="CONDITION_ID" primaryKey="true" required="true" type="BIGINT"/>
+ <table name="SCARAB_CONDITION" idMethod="idbroker" javaName="Condition">
+ <column name="CONDITION_ID" primaryKey="true" required="true" type="BIGINT"/>
<column name="TRANSITION_ID" primaryKey="false" required="false" type="INTEGER"/>
- <column name="MODULE_ID" primaryKey="false" required="false" type="INTEGER"/>
+ <column name="USER_ID" primaryKey="false" required="false" type="INTEGER"/>
+ <column name="MODULE_ID" primaryKey="false" required="false" type="INTEGER"/>
<column name="ISSUE_TYPE_ID" primaryKey="false" required="false" type="INTEGER"/>
- <column name="ATTRIBUTE_ID" primaryKey="false" required="false" type="INTEGER"/>
- <column name="OPTION_ID" primaryKey="false" required="true" type="INTEGER"/>
+ <column name="ATTRIBUTE_ID" primaryKey="false" required="false" type="INTEGER"/>
+ <column name="OPTION_ID" primaryKey="false" required="true" type="INTEGER"/>
+ <column name="OPERATOR" primaryKey="false" required="false" default="0" type="INTEGER"/>
<foreign-key foreignTable="SCARAB_R_MODULE_ATTRIBUTE">
<reference local="MODULE_ID" foreign="MODULE_ID"/>
<reference local="ATTRIBUTE_ID" foreign="ATTRIBUTE_ID"/>
@@ -177,6 +179,9 @@
<reference local="MODULE_ID" foreign="MODULE_ID"/>
<reference local="ISSUE_TYPE_ID" foreign="ISSUE_TYPE_ID"/>
</foreign-key>
+ <foreign-key foreignTable="TURBINE_USER">
+ <reference local="USER_ID" foreign="USER_ID"/>
+ </foreign-key>
</table>
<table name="SCARAB_ATTRIBUTE_GROUP" idMethod="idbroker" javaName="AttributeGroup" description="Groupings in which attributes appear on the page.">
<column name="ATTRIBUTE_GROUP_ID" primaryKey="true" required="true" type="INTEGER" description="Unique identifier."/>
@@ -842,20 +847,36 @@
<index-column name="STATUS"/>
</index>
</table>
- <table name="SCARAB_NOTIFICATION_FILTER" idMethod="none" javaName="NotificationFilter" description="Notification Status table. Used by NotificationManager.">
- <column name="MODULE_ID" primaryKey="true" required="true" type="INTEGER" description="Unique identifier. The MODULE_ID is also a foreign key to SCARAB_MODULE."/>
- <column name="USER_ID" primaryKey="true" javaName="UserId" required="true" type="INTEGER"/>
- <column name="ACTIVITY_TYPE" primaryKey="true" required="true" type="VARCHAR" size="30"/>
- <column name="MANAGER_ID" primaryKey="true" required="true" type="INTEGER" default="0" description="We currently have only one manager (the Notificationmanager). This may change in the future. Currently following values are allowed: 1 = handle notifications via the Scarab NotificationManager. For convenience: If no filter is defined for a specific filter type, notifications are handled by NotificationManager."/>
- <column name="FILTER_STATE" required="true" type="BOOLEANINT" default="0" javaType="primitive" description="The filter state is either 0 = do not handle activites or 1 = handle activities. NOTE: If no filter is defined for a specific ActivityType, Scarab by default handles all notifications via the Scarab Notification manager. If you want to discard notifications of a specific activity type, you must create a NotificationFilter and set the FILTER_STATE to 0."/>
- <column name="SEND_SELF" required="true" type="BOOLEANINT" default="0" javaType="primitive" description="Notifications, which have been triggered by User X will not be sent to self (User X) by default. But if the SELF_SEND flag is set to true (1), user X gets self notified by the Notification Manager."/>
- <column name="SEND_FAILURES" required="true" type="BOOLEANINT" default="0" javaType="primitive" description="For Notifications, which could NOT be sent to a receiver, the Notification Manager generates an online notification by default. But if the SEND_FAILURES flag is set to false (0) failures will be omitted silently."/>
+
+ <!--
+ The following table replaces SCARAB_NOTIFICATION_FILTER.
+ Each user can have multiple rules for sending notifications. There can be at
+ most one rule per activity type and user. Each rule can be accompanied by a
+ set of entries in the SCARAB_CONDITION table, where the RULE_ID is used as
+ foreign key to entries of this table. If SCARAB_CONDITION contains entries
+ for the current module/user/activity_type combination, these entries will
+ be evaluated and eventually the decision is taken if the user will be
+ notified or not.
+ [HD]June,22 2009
+ -->
+ <table name="SCARAB_NOTIFICATION_RULE" idMethod="idbroker" javaName="NotificationRule" description="Notification rule table to determine when a notification has to be sent out to whom. Used by NotificationManager.">
+
+ <column name="RULE_ID" primaryKey="true" required="true" type="INTEGER" description="The unique id of this rule"/>
+ <column name="MODULE_ID" required="true" type="INTEGER" description="The MODULE_ID is also a foreign key to SCARAB_MODULE."/>
+ <column name="USER_ID" required="true" type="INTEGER" javaName="UserId" />
+ <column name="ACTIVITY_TYPE" required="true" type="VARCHAR" size="30"/>
+ <column name="MANAGER_ID" required="true" type="INTEGER" default="0" description="We currently have only one manager (the Notificationmanager). This may change in the future. Currently following values are allowed: 1 = handle notifications via the Scarab NotificationManager. For convenience: If no filter is defined for a specific filter type, notifications are handled by NotificationManager."/>
+ <column name="FILTER_STATE" required="true" type="BOOLEANINT" default="0" javaType="primitive" description="The filter state is either 0 = do not handle activites or 1 = handle activities. NOTE: If no filter is defined for a specific ActivityType, Scarab by default handles all notifications via the Scarab Notification manager. If you want to discard notifications of a specific activity type, you must create a NotificationFilter and set the FILTER_STATE to 0."/>
+ <column name="SEND_SELF" required="true" type="BOOLEANINT" default="0" javaType="primitive" description="Notifications, which have been triggered by User X will not be sent to self (User X) by default. But if the SELF_SEND flag is set to true (1), user X gets self notified by the Notification Manager."/>
+ <column name="SEND_FAILURES" required="true" type="BOOLEANINT" default="0" javaType="primitive" description="For Notifications, which could NOT be sent to a receiver, the Notification Manager generates an online notification by default. But if the SEND_FAILURES flag is set to false (0) failures will be omitted silently."/>
+
<foreign-key foreignTable="TURBINE_USER">
<reference local="USER_ID" foreign="USER_ID"/>
</foreign-key>
<foreign-key foreignTable="SCARAB_MODULE">
<reference local="MODULE_ID" foreign="MODULE_ID"/>
</foreign-key>
+
</table>
<table name="SCARAB_DEFAULT_NOTIFICATION_FILTER" idMethod="none" javaName="NotificationDefaultFilter" description="Notification Status table for module default values. Used by NotificationManager.">
<column name="MODULE_ID" primaryKey="true" required="true" type="INTEGER" description="Unique identifier. The MODULE_ID is also a foreign key to SCARAB_MODULE."/>
@@ -871,4 +892,6 @@
<reference local="MODULE_ID" foreign="MODULE_ID"/>
</foreign-key>
</table>
+
+
</database>
Modified: trunk/src/sql/scarab-id-table-init.sql
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/sql/scarab-id-table-init.sql?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/sql/scarab-id-table-init.sql (original)
+++ trunk/src/sql/scarab-id-table-init.sql 2009-06-27 07:44:10-0700
@@ -26,6 +26,7 @@
insert into ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (45, 'SCARAB_MIT_LISTITEM', 10000, 10);
insert into ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (46, 'SCARAB_R_MODULE_USER_ATTRIBUTE', 10000, 10);
insert into ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (47, 'SCARAB_GLOBAL_PARAMETER', 10000, 10);
+insert into ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (48, 'SCARAB_NOTIFICATION_RULE', 10000, 10);
insert into ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (100, 'SCARAB_TRANSITION', 10000, 10);
insert into ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (101, 'SCARAB_CONDITION', 10000, 10);
insert into ID_TABLE (id_table_id, table_name, next_id, quantity) VALUES (999, 'ID_TABLE', 1000, 1);
Added: trunk/src/sql/upgrade/upgrade-0.23-notification.sql
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/sql/upgrade/upgrade-0.23-notification.sql?view=markup&pathrev763
=============================================================================--- (empty file)
+++ trunk/src/sql/upgrade/upgrade-0.23-notification.sql 2009-06-27 07:44:10-0700
@@ -0,0 +1,107 @@
+#
+# This upgrade script creates a new SCARAB_NOTIFICATION_RULE table and
+# adds the content from the current SCARAB_NOTIFICATION_FILTER table
+# It also supplies a new entry into ID_TABLE for automatic creation of
+# unique RUL_ID entries.
+#
+# Created by: Hussayn Dabbous [email protected]
+#
+# IMPORTANT NOTE: If you encounter problems during the conversion,
+# most probably your database used a mix of MyIsam- and InnoDb- tables.
+# The problem is that you can not define foreign keys between tables
+# which are created on different engines.
+#
+# One possible solution is (worked for me) :
+#
+# - Dump your database
+# - edit the dumpfile and change all occurances of "engine=MyIsam" to
+# engine="InnoDB"
+# - recreate your database with the modified dumpfile.
+# - Apply this script again. Now it should work.
+#
+# If you run this script multiple times, you will see errors:
+#
+# $ mysql -f asp < upgrade-0.23-notification.sql
+# ERROR 1060 (42S21) at line 81: Duplicate column name 'USER_ID'
+# ERROR 1005 (HY000) at line 85: Can't create table '.\asp\#sql-20c_23.frm' (errno: 121)
+# ERROR 1062 (23000) at line 94: Duplicate entry '48' for key 1
+#
+# The errors indicate that the script has been processed before. If you see
+# different erors, probably something else is going on. Check that!!!
+#
+# You may want to run the script using "mysql -f scarab < upgrade-0.23-notification.sql"
+#
+# Check that everything is OK after you run the script:
+#
+# 1.) The table SCARAB_CONDITION has a new Column USER_ID
+# 2.) The table SCARAB_NOTIFICATION_RULE exists and has got
+# its content copied from SCARAB_NOTIFICATION_FILTER
+#
+# If these conditions are met, the upgrade has bee successfull.
+# -----------------------------------------------------------------------
+# SCARAB_NOTIFICATION_RULE
+# -----------------------------------------------------------------------
+drop table if exists SCARAB_NOTIFICATION_RULE;
+
+CREATE TABLE SCARAB_NOTIFICATION_RULE
+(
+ RULE_ID INTEGER NOT NULL AUTO_INCREMENT,
+ MODULE_ID INTEGER NOT NULL,
+ USER_ID INTEGER NOT NULL,
+ ACTIVITY_TYPE VARCHAR(30) NOT NULL,
+ MANAGER_ID INTEGER default 0 NOT NULL,
+ FILTER_STATE INTEGER default 0 NOT NULL,
+ SEND_SELF INTEGER default 0 NOT NULL,
+ SEND_FAILURES INTEGER default 0 NOT NULL,
+ PRIMARY KEY(RULE_ID));
+
+# -------------------------------------------------------------------------------
+#copy the data from SCARAB_NOTIFICATION_FILTER
+# -------------------------------------------------------------------------------
+insert into SCARAB_NOTIFICATION_RULE (MODULE_ID, USER_ID, ACTIVITY_TYPE, MANAGER_ID, FILTER_STATE, SEND_SELF, SEND_FAILURES)
+ select MODULE_ID, USER_ID, ACTIVITY_TYPE, MANAGER_ID, FILTER_STATE, SEND_SELF, SEND_FAILURES from SCARAB_NOTIFICATION_FILTER;
+
+
+# -------------------------------------------------------------------------------
+#remove the auto-increment
+# -------------------------------------------------------------------------------
+ALTER TABLE SCARAB_NOTIFICATION_RULE CHANGE RULE_ID RULE_ID INTEGER NOT NULL;
+
+ALTER TABLE SCARAB_NOTIFICATION_RULE
+ ADD CONSTRAINT SCARAB_NOTIFICATION_RULE_FK_1
+ FOREIGN KEY (USER_ID)
+ REFERENCES TURBINE_USER(USER_ID)
+ ;
+ALTER TABLE SCARAB_NOTIFICATION_RULE
+ ADD CONSTRAINT SCARAB_NOTIFICATION_RULE_FK_2
+ FOREIGN KEY (MODULE_ID)
+ REFERENCES SCARAB_MODULE(MODULE_ID)
+ ;
+
+ALTER TABLE SCARAB_CONDITION
+ ADD ( USER_ID INTEGER )
+ ;
+
+ALTER TABLE SCARAB_CONDITION
+ ADD ( OPERATOR INTEGER NOT NULL DEFAULT 0 )
+ ;
+
+ALTER TABLE SCARAB_CONDITION
+ ADD CONSTRAINT SCARAB_CONDITION_FK_6
+ FOREIGN KEY (USER_ID)
+ REFERENCES TURBINE_USER (USER_ID)
+ ;
+
+# -------------------------------------------------------------------------------
+# create additional ID_TABLE entry
+# -------------------------------------------------------------------------------
+insert into ID_TABLE (id_table_id, table_name, next_id, quantity)
+ select 48, 'SCARAB_NOTIFICATION_RULE', count(*) + 1, 10 from SCARAB_NOTIFICATION_FILTER;
+
+
+# -------------------------------------------------------------------------------
+# drop the old NOTIFICATION_TABLE
+# For the moment keep table SCARAB_NOTIFICATION_FILTER as a backup.
+# Remove NOTIFICATION_FILTER in the next release
+# -------------------------------------------------------------------------------
+#drop table SCARAB_NOTIFICATION_FILTER;
Modified: trunk/src/webapp/WEB-INF/templates/navigations/Administration.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/navigations/Administration.vm?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/webapp/WEB-INF/templates/navigations/Administration.vm (original)
+++ trunk/src/webapp/WEB-INF/templates/navigations/Administration.vm 2009-06-27 07:44:10-0700
@@ -11,6 +11,7 @@
#set ($allowUSI = $link.isAllowed("admin,UpdateSearchIndex.vm"))
#set ($allowCustomize = $data.user.isUserAnonymous()=úlse)
+
#if ($allowMUS || $allowAU || $allowMR || $allowAR || $allowGATS || $allowGAS || $allowMAT || $allowMM || $allowA || $allowCP || $allowUSI)
#set ($adminMenu = $data.Parameters.getString($scarabG.Constant.CURRENT_ADMIN_MENU, ""))
@@ -82,6 +83,11 @@
<div>$link.setPage("admin,ManageUserSearch.vm").setPathInfo("newSearch","true").setPathInfo($scarabG.Constant.CURRENT_ADMIN_MENU, "5").setLabel("$l10n.Users")</div>
#end
#end
+
+ #if ( $$allowCustomize )
+ <div>$link.setPage("notifications,NotificationCustomize.vm").setLabel("$l10n.EditNotificationRules")</div>
+ #end
+
#end
</div>
</div>
Modified: trunk/src/webapp/WEB-INF/templates/screens/admin/ConditionEdit.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/admin/ConditionEdit.vm?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/webapp/WEB-INF/templates/screens/admin/ConditionEdit.vm (original)
+++ trunk/src/webapp/WEB-INF/templates/screens/admin/ConditionEdit.vm 2009-06-27 07:44:10-0700
@@ -2,21 +2,26 @@
#set ($groupId = $data.Parameters.getString("groupid"))
## Set values depending on conditioned object
#set ($objType = $data.Parameters.getInteger("obj_type"))
-#set ($transitionId = $data.Parameters.getInteger("transition_id"))
#set ($attributeId = $data.Parameters.getInteger("attId"))
+#set ($transitionId = $data.Parameters.getInteger("transition_id"))
#if ($objType==$scarabG.Constant.TRANSITION_OBJECT)
+
#set ($transition = $scarabR.getTransition($transitionId))
#set ($attribute = $transition.attribute)
#set ($object = $transition)
#set ($conditionMsg = $l10n.format('ConditionOnTransition', [$transition.attribute.Name]))
#set ($optionList = $scarabR.sortedAttributeOptions)
+
#elseif ($objType==$scarabG.Constant.GLOBAL_ATTRIBUTE_OBJECT)
+
#set ($attribute = $scarabR.getAttribute($attributeId))
#set ($object = $attribute)
#set ($conditionMsg = "$l10n.format('ConditionOnGlobalAttribute', [$attribute.Name])")
#set ($optionList = $scarabR.sortedAttributeOptions)
+
#elseif ($objType==$scarabG.Constant.MODULE_ATTRIBUTE_OBJECT)
+
#set ($groupId = $data.Parameters.getString("groupId"))
#set ($attribute = $scarabR.getAttribute($attributeId))
#set ($issueType = $scarabR.getIssueType($data.getParameters().get("issueTypeId")))
@@ -25,13 +30,28 @@
#set ($object = $rma)
#set ($conditionMsg = $l10n.format('ConditionOnModuleAttribute', [$attribute.Name, $module.RealName]))
#set ($optionList = $scarabR.getSortedAttributeOptionsForRMIT($rmit))
+
#elseif ($objType==$scarabG.Constant.BLOCKED_MODULE_ISSUE_TYPE_OBJECT)
+
#set ($issueType = $scarabR.getIssueType($data.getParameters().get("issueTypeId")))
#set ($rmit = $scarabR.getRModuleIssueType($module.moduleId, $issueType.issueTypeId))
#set ($object = $rmit)
#set ($conditionMsg = $l10n.format('BlockingConditionOnIssueType', $object.IssueType.Name, $object.Module.RealName))
#set ($optionList = $scarabR.getSortedAttributeOptionsForRMIT($rmit))
+
+#elseif ($objType==$scarabG.Constant.NOTIFICATION_ATTRIBUTE_OBJECT)
+
+ #set ($transition = $scarabR.getTransition($transitionId))
+ #set ($attribute = $transition.attribute)
+ #set ($notification = $scarabG.getEmptyNotificationFor($user, $module))
+ #set ($object = $notification)
+ #set ($conditionMsg = "$l10n.Notifications")
+ #set ($ConditionsCurrentValue = "n.a.")
+ #set ($optionList = $scarabR.getSortedAttributeOptionsForModule($module))
+
#end
+
+#set ($combineWith = 0)
#set ($attgroup = $intake.ConditionEdit.Default)
<div class="app" id="div3-0-2-0">
@@ -54,8 +74,11 @@
<h3>$l10n.ConditionDefinition</h3>
<div class="colbar">
-$l10n.ConditionsExplanation1<br/>
+
+$l10n.ConditionsExplanation1
$l10n.ConditionsExplanation2<br/>
+$l10n.ConditionsExplanation3
+</ul>
</div>
<div class="axial">
<table cellpadding="3" cellspacing="2" border="0">
@@ -68,9 +91,19 @@
<td>
#foreach ($o in $object.Conditions)
$o.attributeOption.attribute.name = $o.attributeOption.name<br/>
+ #set ($combineWith = $o.get(0).Operator)
#end
</td>
</tr>
+
+<tr>
+ <th nowrap="nowrap">combine attributes with</th>
+ <td>
+ <input type="radio" name="combineWith" value="0" #if ($combineWith==0) checked="checked" #end> $l10n.or</input>
+ <input type="radio" name="combineWith" value="1"#if ($combineWith==1) checked="checked" #end> $l10n.and </input>
+ </td>
+</tr>
+
<tr>
<th>$l10n.ConditionsNewValue</th>
<td>
Modified: trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationCustomize.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationCustomize.vm?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationCustomize.vm (original)
+++ trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationCustomize.vm 2009-06-27 07:44:10-0700
@@ -25,6 +25,7 @@
#set ($module = $scarabR.CurrentModule)
#set ($moduleId = $module.moduleId)
#set ($activityCodes = $scarabG.getAllNotificationTypeCodes())
+<div class="axial">
<table>
<tr>
<th nowrap="nowrap">$l10n.ActivityType</th>
@@ -53,28 +54,50 @@
</td>
</tr>
#set ($descWrittenúlse)
+ #set ($notification = $scarabG.getEmptyNotificationFor($user, $module))
#foreach ($activityCode in $activityCodes)
- #set ($filter = $scarabG.getNotificationFilter($moduleId, $userId, $activityCode))
+ #set ($rule = $scarabG.getNotificationRule($moduleId, $userId, $activityCode))
+ #set ($label = $l10n.get($scarabG.getActivityTypeLabelResource($activityCode)))
#indexedRows($velocityCount)
<th nowrap="nowrap">
- #set ($label = $l10n.get($scarabG.getActivityTypeLabelResource($activityCode)))
-
- ##if ($activityCode.equals("attribute_changed"))
- ## discard until implemented (HD 30-Mai-2006)
- ## <a href="CustomizeAttributeNotifications.vm">$label ...</a>
- ##else
- $label
- ##end
+ $label
</th>
- <td><input type="checkbox" name="${activityCode}:status" #if ($filter.getFilterState()) checked="checked"#end></td>
- <td><input type="checkbox" name="${activityCode}:self" #if ($filter.getSendSelf()) checked="checked"#end></td>
- <td><input type="checkbox" name="${activityCode}:fail" #if ($filter.getSendFailures())checked="checked"#end></td>
+ <td><input type="checkbox" name="${activityCode}:status" #if ($rule.getFilterState()) checked="checked"#end></td>
+ <td><input type="checkbox" name="${activityCode}:self" #if ($rule.getSendSelf()) checked="checked"#end></td>
+ <td><input type="checkbox" name="${activityCode}:fail" #if ($rule.getSendFailures())checked="checked"#end></td>
+
</tr>
#end
+
+ #indexedRows($velocityCount)
+ <td nowrap="nowrap">
+ $l10n.NotificationConditions
+ </td>
+ <td colspan="3" nowrap="nowrap">
+ #if ($notification.isConditioned())
+ #set ($requiredOptions = $notification.Conditions)
+ #foreach ($o in $requiredOptions)
+ $o.attributeOption.attribute.name = $o.attributeOption.name<br/>
+ #end
+ #else
+ <em>$l10n.NoNotificationConditionsDefined</em>
+ #end
+
+ #if ($notification.isConditioned())
+ #set ($msgCondition = $l10n.EditConditions)
+ #else
+ #set ($msgCondition = $l10n.AddConditions)
+ #end
+ $link.init($data)
+ </td>
+ </tr>
</table>
+</div>
<div class="functnbar3">
<input type="submit" value="$l10n.Save" name="eventSubmit_doCustomize" />
+ <input type="button" value="$l10n.EditConditions"
+ onClick="location.href='$link.setPage("admin,ConditionEdit.vm").addPathInfo("$scarabG.Constant.CANCEL_TEMPLATE","notifications,NotificationCustomize.vm").addPathInfo("obj_type", "$scarabG.Constant.NOTIFICATION_ATTRIBUTE_OBJECT").addPathInfo("attId", "$rule.RuleId")'" />
</div>
##<p class="paginate">« $l10n.Previous | 1 of 1 | $l10n.Next »</p>
Modified: trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationList.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationList.vm?view=diff&pathrev763&r1762&r2763
=============================================================================--- trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationList.vm (original)
+++ trunk/src/webapp/WEB-INF/templates/screens/notifications/NotificationList.vm 2009-06-27 07:44:10-0700
@@ -7,8 +7,6 @@
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td nowrap="nowrap" width="100%">$l10n.NotificationList</td>
- ##Enter filter editor
- <td nowrap="nowrap" style="font-size:9px;">$link.setPage("notifications,NotificationCustomize.vm").setLabel("$l10n.EditNotificationRules")</td>
</tr>
</table>
</h3>
Added: trunk/src/webapp/images/customize.gif
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/images/customize.gif?view=markup&pathrev763
=============================================================================Binary file. No diff available.
------------------------------------------------------
http://scarab.tigris.org/ds/viewMessage.do?dsForumId=3577&dsMessageId=2365967