1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.watchlist.internal.notification

File WatchListMessageDataExtractor.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

16
52
6
1
218
125
18
0.35
8.67
6
3

Classes

Class Line # Actions
WatchListMessageDataExtractor 54 52 0% 18 7
0.905405490.5%
 

Contributing tests

This file is covered by 10 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.watchlist.internal.notification;
21   
22    import java.util.HashSet;
23    import java.util.List;
24    import java.util.Map;
25    import java.util.Set;
26   
27    import javax.mail.Address;
28   
29    import org.slf4j.Logger;
30    import org.slf4j.LoggerFactory;
31    import org.xwiki.context.Execution;
32    import org.xwiki.mail.internal.factory.usersandgroups.AddressUserDataExtractor;
33    import org.xwiki.model.reference.DocumentReference;
34    import org.xwiki.model.reference.DocumentReferenceResolver;
35    import org.xwiki.model.reference.WikiReference;
36    import org.xwiki.watchlist.internal.DefaultWatchListStore;
37    import org.xwiki.watchlist.internal.WatchListEventMatcher;
38    import org.xwiki.watchlist.internal.api.WatchListEvent;
39    import org.xwiki.watchlist.internal.job.WatchListJob;
40   
41    import com.xpn.xwiki.XWiki;
42    import com.xpn.xwiki.XWikiContext;
43    import com.xpn.xwiki.doc.XWikiDocument;
44    import com.xpn.xwiki.internal.plugin.rightsmanager.UserDataExtractor;
45    import com.xpn.xwiki.objects.BaseObject;
46   
47    /**
48    * Extracts from the current subscriber the {@link WatchListMessageData} to be used when notifying him of events that he
49    * is interested in. Handles duplicates and skips emails that have already been processed.
50    *
51    * @version $Id: 30fbbd2bfed7b04072a3b665dd608305647d9c62 $
52    * @since 7.1M1
53    */
 
54    public class WatchListMessageDataExtractor implements UserDataExtractor<WatchListMessageData>
55    {
56    private static final Logger LOGGER = LoggerFactory.getLogger(AddressUserDataExtractor.class);
57   
58    private EventsAndSubscribersSource source;
59   
60    private Set<Address> processedAddresses;
61   
62    private WatchListEventMatcher eventMatcher;
63   
64    private Execution execution;
65   
66    private AddressUserDataExtractor addressExtractor;
67   
68    private DocumentReferenceResolver<String> explicitDocumentReferenceResolver;
69   
70    private Map<String, Object> parameters;
71   
72    private boolean skipContextUser;
73   
74    /**
75    * Constructor.
76    *
77    * @param source the input data to iterate over
78    * @param parameters the message factory's parameters
79    * @param eventMatcher user to determine if a subscriber is interested in an event
80    * @param execution used for accessing the subscriber's profile
81    * @param explicitDocumentReferenceResolver the resolver to use for transforming group member strings into
82    * {@link org.xwiki.model.reference.DocumentReference}
83    */
 
84  41 toggle public WatchListMessageDataExtractor(EventsAndSubscribersSource source, Map<String, Object> parameters,
85    WatchListEventMatcher eventMatcher, Execution execution,
86    DocumentReferenceResolver<String> explicitDocumentReferenceResolver)
87    {
88  41 this.source = source;
89  41 this.parameters = parameters;
90  41 this.eventMatcher = eventMatcher;
91  41 this.execution = execution;
92  41 this.explicitDocumentReferenceResolver = explicitDocumentReferenceResolver;
93   
94    // Reuse the existing Address extractor
95  41 this.addressExtractor = new AddressUserDataExtractor();
96   
97    // Init a clean set of processed addresses.
98  41 this.processedAddresses = new HashSet<>();
99   
100    // Read and cache the skipContextUser's parameter value, if any was specified.
101  41 Boolean skipContextUserValue =
102    (Boolean) parameters.get(WatchListEventMimeMessageFactory.SKIP_CONTEXT_USER_PARAMETER);
103  41 if (skipContextUserValue != null && Boolean.TRUE.equals(skipContextUserValue)) {
104  30 skipContextUser = true;
105    }
106    }
107   
 
108  0 toggle @Override
109    public WatchListMessageData extractFromSuperadmin(DocumentReference reference)
110    {
111  0 return null;
112    }
113   
 
114  0 toggle @Override
115    public WatchListMessageData extractFromGuest(DocumentReference reference)
116    {
117  0 return null;
118    }
119   
 
120  41 toggle @Override
121    public WatchListMessageData extract(DocumentReference subscriberReference, XWikiDocument document,
122    BaseObject userObject)
123    {
124  41 WatchListMessageData result = null;
125   
126  41 try {
127  41 if (skipContextUser && subscriberReference.equals(getXWikiContext().getUserReference())) {
128    // If the current context user should not be notified of events that apparently interest him, stop.
129  6 return null;
130    }
131   
132    // Get only the events that the current subscriber is interested in.
133  35 List<WatchListEvent> matchingEvents =
134    eventMatcher.getMatchingVisibleEvents(source.getEvents(), document.getPrefixedFullName());
135   
136  35 if (matchingEvents.size() == 0) {
137    // If there are no interesting events, stop.
138  24 return null;
139    }
140   
141  11 String firstName = userObject.getStringValue("first_name");
142  11 String lastName = userObject.getStringValue("last_name");
143   
144  11 Address address = addressExtractor.extract(subscriberReference, document, userObject);
145  11 if (address == null || processedAddresses.contains(address)) {
146    // Make sure we skip users with no email set or emails we have already sent to.
147  3 return null;
148    }
149    // Remember emails we have already sent to.
150  8 processedAddresses.add(address);
151   
152  8 DocumentReference templateReference = getTemplateReference(subscriberReference);
153   
154  8 result =
155    new WatchListMessageData(subscriberReference, templateReference, firstName, lastName, address,
156    matchingEvents);
157   
158    } catch (Exception e) {
159  0 LOGGER.error("Failed to retrieve information for user [{}]", subscriberReference, e);
160    }
161   
162  8 return result;
163    }
164   
 
165  8 toggle private DocumentReference getTemplateReference(DocumentReference subscriberReference)
166    {
167  8 DocumentReference result = null;
168   
169    // In the case of WatchListJob for example, this is filled in by the admin so we must interpret it to determine
170    // which actual document to use as template.
171  8 String templateStringReference = (String) parameters.get(WatchListEventMimeMessageFactory.TEMPLATE_PARAMETER);
172   
173  8 if (templateStringReference.contains(DefaultWatchListStore.WIKI_SPACE_SEP)) {
174    // If the configured template is already an absolute reference it's meant to force the template.
175  2 result = explicitDocumentReferenceResolver.resolve(templateStringReference);
176  2 return result;
177    }
178   
179    // Try on the user's wiki
180  6 WikiReference userWikiReference = subscriberReference.getWikiReference();
181  6 result = explicitDocumentReferenceResolver.resolve(templateStringReference, userWikiReference);
182  6 XWikiContext context = getXWikiContext();
183  6 XWiki wiki = context.getWiki();
184  6 if (wiki.exists(result, context)) {
185  3 return result;
186    }
187   
188    // Try on the current (context) wiki.
189  3 WikiReference currentWikiReference = new WikiReference(context.getWikiId());
190  3 result = explicitDocumentReferenceResolver.resolve(templateStringReference, currentWikiReference);
191  3 if (wiki.exists(result, context)) {
192  2 return result;
193    }
194   
195    /* Try the default locations. */
196   
197    // Try the default on the context wiki
198  1 result = explicitDocumentReferenceResolver.resolve(WatchListJob.DEFAULT_EMAIL_TEMPLATE, currentWikiReference);
199  1 if (wiki.exists(result, context)) {
200  0 return result;
201    }
202   
203    // Try the default on the main wiki (final case)
204  1 WikiReference mainWikiReference = new WikiReference(context.getMainXWiki());
205  1 result = explicitDocumentReferenceResolver.resolve(WatchListJob.DEFAULT_EMAIL_TEMPLATE, mainWikiReference);
206   
207  1 return result;
208    }
209   
 
210  36 toggle private XWikiContext getXWikiContext()
211    {
212  36 XWikiContext context =
213    (XWikiContext) this.execution.getContext().getProperty(XWikiContext.EXECUTIONCONTEXT_KEY);
214   
215  36 return context;
216    }
217   
218    }