use of org.xwiki.notifications.filters.expression.generics.AbstractOperatorNode in project xwiki-platform by xwiki.
the class QueryGenerator method handleEventPreferences.
/**
* For each notification preference of the given user, add a constraint on the events to
* - have one of the notification types that have been subscribed by the user;
* - have a date superior to the start date corresponding to this type;
* - match the custom defined user filters.
*
* @param user the current user
* @param preferences a list of the user preferences
* @return a list of maps that contains query parameters
* @throws NotificationException if an error occurred
*/
private AbstractOperatorNode handleEventPreferences(DocumentReference user, List<NotificationPreference> preferences) throws NotificationException {
AbstractOperatorNode preferencesNode = null;
// Filter the notification preferences that are not bound to a specific EVENT_TYPE
Iterator<NotificationPreference> it = preferences.stream().filter(pref -> pref.getProperties().containsKey(NotificationPreferenceProperty.EVENT_TYPE)).iterator();
while (it.hasNext()) {
NotificationPreference preference = it.next();
AbstractOperatorNode preferenceTypeNode = new AndNode(new EqualsNode(value(EventProperty.TYPE), value((String) preference.getProperties().get(NotificationPreferenceProperty.EVENT_TYPE))), new GreaterThanNode(value(EventProperty.DATE), value(preference.getStartDate())));
// Get the notification filters that can be applied to the current preference
Collection<NotificationFilter> filters = notificationFilterManager.getFilters(user, preference);
for (NotificationFilter filter : filters) {
ExpressionNode node = filter.filterExpression(user, preference);
if (node != null && node instanceof AbstractOperatorNode) {
preferenceTypeNode = preferenceTypeNode.and((AbstractOperatorNode) node);
}
}
if (preferencesNode == null) {
preferencesNode = preferenceTypeNode;
} else {
preferencesNode = preferencesNode.or(preferenceTypeNode);
}
}
return preferencesNode;
}
use of org.xwiki.notifications.filters.expression.generics.AbstractOperatorNode in project xwiki-platform by xwiki.
the class ScopeNotificationFilterExpressionGenerator method handleExclusiveFilters.
private AbstractOperatorNode handleExclusiveFilters(AbstractOperatorNode node, ScopeNotificationFilterPreferencesHierarchy preferences) {
AbstractOperatorNode topNode = node;
Iterator<ScopeNotificationFilterPreference> it = preferences.getExclusiveFiltersThatHasNoParents();
// Handle exclusive filters
while (it.hasNext()) {
ScopeNotificationFilterPreference pref = it.next();
// For each exclusive filter, we want to generate a query to black list the location with a white list of
// sub locations.
// Ex: "wiki1:Space1" is blacklisted but:
// - "wiki1:Space1.Space2" is white listed
// - "wiki1:Space1.Space3" is white listed too
// The filterNode is something like "NOT (event.location = A)".
AbstractOperatorNode filterNode = generateNode(pref);
// Children are a list of inclusive filters located under the current one.
for (ScopeNotificationFilterPreference childFilter : pref.getChildren()) {
// child filter is something like "event.location = A.B"
filterNode = filterNode.or(generateNode(childFilter));
}
// Chain this filter to the previous one
if (topNode == null) {
topNode = filterNode;
} else {
topNode = topNode.and(filterNode);
}
}
return topNode;
}
use of org.xwiki.notifications.filters.expression.generics.AbstractOperatorNode in project xwiki-platform by xwiki.
the class QueryGenerator method generateQueryExpression.
/**
* Generate the query.
*
* @param user user interested in the notifications
* @param format only match notifications enabled for that format
* @param endDate do not return events happened after this date
* @param startDate do not return events happened before this date. Note that since 9.7RC1, this start date is
* completely optional, {@link NotificationPreference#getStartDate()} should be used for more granular control on
* notifications
* @param blackList list of ids of blacklisted events to not return (to not get already known events again)
* @return the query to execute
*
* @throws NotificationException if error happens
* @throws QueryException if error happens
*
* @since 9.8RC1
*/
public ExpressionNode generateQueryExpression(DocumentReference user, NotificationFormat format, Date endDate, Date startDate, List<String> blackList) throws NotificationException, QueryException {
// First: get the active preferences of the given user
List<NotificationPreference> preferences = notificationPreferenceManager.getPreferences(user, true, format);
// Ensure that we have at least one filter preference that is active
if (preferences.isEmpty() && notificationFilterManager.getFilterPreferences(user).stream().noneMatch(NotificationFilterPreference::isActive)) {
return null;
}
AbstractOperatorNode topNode = null;
// Condition 1: (maybe) events have happened after the given start date
if (startDate != null) {
topNode = new GreaterThanNode(new PropertyValueNode(EventProperty.DATE), new DateValueNode(startDate));
}
// Condition 2: handle other preferences
AbstractOperatorNode preferencesNode = handleEventPreferences(user, preferences);
// Condition 3: handle exclusive global notification filters
AbstractOperatorNode globalExclusiveFiltersNode = handleExclusiveGlobalFilters(user, format);
if (globalExclusiveFiltersNode != null) {
if (preferencesNode == null) {
preferencesNode = globalExclusiveFiltersNode;
} else {
preferencesNode = preferencesNode.and(globalExclusiveFiltersNode);
}
}
// Condition 4: handle inclusive global notification filters
AbstractOperatorNode globalInclusiveFiltersNode = handleInclusiveGlobalFilters(user, format);
if (globalInclusiveFiltersNode != null) {
if (preferencesNode == null) {
preferencesNode = globalInclusiveFiltersNode;
} else {
preferencesNode = preferencesNode.or(globalInclusiveFiltersNode);
}
}
// Mix all these conditions
if (preferencesNode != null) {
if (topNode != null) {
topNode = topNode.and(preferencesNode);
} else {
topNode = preferencesNode;
}
}
// Other basic filters
topNode = handleBlackList(blackList, topNode);
topNode = handleEndDate(endDate, topNode);
topNode = handleHiddenEvents(topNode);
topNode = handleWiki(user, topNode);
topNode = handleOrder(topNode);
return topNode;
}
use of org.xwiki.notifications.filters.expression.generics.AbstractOperatorNode in project xwiki-platform by xwiki.
the class ScopeNotificationFilterExpressionGenerator method handleTopLevelInclusiveFilters.
private AbstractOperatorNode handleTopLevelInclusiveFilters(AbstractOperatorNode node, ScopeNotificationFilterPreferencesHierarchy preferences) {
AbstractOperatorNode topNode = node;
Iterator<ScopeNotificationFilterPreference> it = preferences.getInclusiveFiltersThatHasNoParents();
while (it.hasNext()) {
ScopeNotificationFilterPreference pref = it.next();
if (topNode == null) {
topNode = generateNode(pref);
} else {
topNode = topNode.or(generateNode(pref));
}
}
return topNode;
}
use of org.xwiki.notifications.filters.expression.generics.AbstractOperatorNode in project xwiki-platform by xwiki.
the class ScopeNotificationFilterExpressionGenerator method filterExpression.
/**
* Generate a filter expression for the given user and event type according to the scope notification filter
* preferences.
* @param user user for who we display notifications
* @param eventType type of the event on which we are filtering
* @param format the format of the notification
* @return the expression node corresponding to the filter
*/
public AbstractOperatorNode filterExpression(DocumentReference user, String eventType, NotificationFormat format) {
// The node we construct
AbstractOperatorNode topNode = null;
// Get the filters to handle
ScopeNotificationFilterPreferencesHierarchy preferences = scopeNotificationFilterPreferencesGetter.getScopeFilterPreferences(user, eventType, format);
// The aim is to generate a black list with exceptions (handleExclusiveFilters) and a white
// list (handleTopLevelInclusiveFilters).
// It is a complex query, for more information see: https://jira.xwiki.org/browse/XWIKI-14713
topNode = handleExclusiveFilters(topNode, preferences);
topNode = handleTopLevelInclusiveFilters(topNode, preferences);
return topNode;
}
Aggregations