001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.social.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.WebKeys;
022    import com.liferay.portal.service.ServiceContext;
023    import com.liferay.portal.service.ServiceContextFactory;
024    import com.liferay.portal.theme.ThemeDisplay;
025    import com.liferay.portal.util.PortalUtil;
026    import com.liferay.portal.util.PropsValues;
027    import com.liferay.portlet.social.model.SocialActivity;
028    import com.liferay.portlet.social.model.SocialActivityFeedEntry;
029    import com.liferay.portlet.social.model.SocialActivityInterpreter;
030    import com.liferay.portlet.social.model.SocialActivitySet;
031    import com.liferay.portlet.social.model.impl.SocialActivityInterpreterImpl;
032    import com.liferay.portlet.social.model.impl.SocialRequestInterpreterImpl;
033    import com.liferay.portlet.social.service.base.SocialActivityInterpreterLocalServiceBaseImpl;
034    import com.liferay.registry.Filter;
035    import com.liferay.registry.Registry;
036    import com.liferay.registry.RegistryUtil;
037    import com.liferay.registry.ServiceReference;
038    import com.liferay.registry.ServiceRegistration;
039    import com.liferay.registry.ServiceTracker;
040    import com.liferay.registry.ServiceTrackerCustomizer;
041    import com.liferay.registry.collections.ServiceRegistrationMap;
042    import com.liferay.registry.collections.ServiceRegistrationMapImpl;
043    
044    import java.util.ArrayList;
045    import java.util.HashMap;
046    import java.util.List;
047    import java.util.Map;
048    
049    import javax.servlet.http.HttpServletRequest;
050    
051    /**
052     * The social activity interpreter local service. Activity interpreters are
053     * classes responsible for translating activity records into human readable
054     * form. This service holds a list of interpreters and provides methods to add
055     * or remove items from this list.
056     *
057     * <p>
058     * Activity interpreters use the language files to get text fragments based on
059     * the activity's type and the type of asset on which the activity was done.
060     * Interpreters are created for specific asset types and are only capable of
061     * translating activities done on assets of those types. As an example, there is
062     * an interpreter BlogsActivityInterpreter that can only translate activity
063     * records for blog entries.
064     * </p>
065     *
066     * @author Brian Wing Shun Chan
067     */
068    public class SocialActivityInterpreterLocalServiceImpl
069            extends SocialActivityInterpreterLocalServiceBaseImpl {
070    
071            /**
072             * Adds the activity interpreter to the list of available interpreters.
073             *
074             * @param activityInterpreter the activity interpreter
075             */
076            @Override
077            public void addActivityInterpreter(
078                    SocialActivityInterpreter activityInterpreter) {
079    
080                    Registry registry = RegistryUtil.getRegistry();
081    
082                    Map<String, Object> properties = new HashMap<>();
083    
084                    SocialActivityInterpreterImpl activityInterpreterImpl =
085                            (SocialActivityInterpreterImpl)activityInterpreter;
086    
087                    properties.put(
088                            "javax.portlet.name", activityInterpreterImpl.getPortletId());
089    
090                    ServiceRegistration<SocialActivityInterpreter> serviceRegistration =
091                            registry.registerService(
092                                    SocialActivityInterpreter.class, activityInterpreter,
093                                    properties);
094    
095                    _serviceRegistrations.put(activityInterpreter, serviceRegistration);
096            }
097    
098            @Override
099            public void afterPropertiesSet() {
100                    Registry registry = RegistryUtil.getRegistry();
101    
102                    Filter filter = registry.getFilter(
103                            "(&(javax.portlet.name=*)(objectClass=" +
104                                    SocialActivityInterpreter.class.getName() + "))");
105    
106                    _serviceTracker = registry.trackServices(
107                            filter, new SocialActivityInterpreterServiceTrackerCustomizer());
108    
109                    _serviceTracker.open();
110            }
111    
112            /**
113             * Removes the activity interpreter from the list of available interpreters.
114             *
115             * @param activityInterpreter the activity interpreter
116             */
117            @Override
118            public void deleteActivityInterpreter(
119                    SocialActivityInterpreter activityInterpreter) {
120    
121                    ServiceRegistration<SocialActivityInterpreter> serviceRegistration =
122                            _serviceRegistrations.remove(activityInterpreter);
123    
124                    if (serviceRegistration != null) {
125                            serviceRegistration.unregister();
126                    }
127            }
128    
129            @Override
130            public Map<String, List<SocialActivityInterpreter>>
131                    getActivityInterpreters() {
132    
133                    return _activityInterpreters;
134            }
135    
136            @Override
137            public List<SocialActivityInterpreter> getActivityInterpreters(
138                    String selector) {
139    
140                    return _activityInterpreters.get(selector);
141            }
142    
143            /**
144             * @deprecated As of 6.2.0, replaced by {@link #interpret(String,
145             *             SocialActivity, ServiceContext)}
146             */
147            @Deprecated
148            @Override
149            public SocialActivityFeedEntry interpret(
150                    SocialActivity activity, ThemeDisplay themeDisplay) {
151    
152                    ServiceContext serviceContext = null;
153    
154                    try {
155                            serviceContext = ServiceContextFactory.getInstance(
156                                    themeDisplay.getRequest());
157                    }
158                    catch (Exception e) {
159                            return null;
160                    }
161    
162                    return interpret(StringPool.BLANK, activity, serviceContext);
163            }
164    
165            /**
166             * Creates a human readable activity feed entry for the activity using an
167             * available compatible activity interpreter.
168             *
169             * <p>
170             * This method finds the appropriate interpreter for the activity by going
171             * through the available interpreters and asking them if they can handle the
172             * asset type of the activity.
173             * </p>
174             *
175             * @param  selector the context in which the activity interpreter is used
176             * @param  activity the activity to be translated to human readable form
177             * @param  serviceContext the service context to be applied
178             * @return the activity feed that is a human readable form of the activity
179             *         record or <code>null</code> if a compatible interpreter is not
180             *         found
181             */
182            @Override
183            public SocialActivityFeedEntry interpret(
184                    String selector, SocialActivity activity,
185                    ServiceContext serviceContext) {
186    
187                    HttpServletRequest request = serviceContext.getRequest();
188    
189                    if (request == null) {
190                            return null;
191                    }
192    
193                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
194                            WebKeys.THEME_DISPLAY);
195    
196                    try {
197                            if (activity.getUserId() == themeDisplay.getDefaultUserId()) {
198                                    return null;
199                            }
200                    }
201                    catch (Exception e) {
202                            _log.error(e, e);
203                    }
204    
205                    if (activity.getMirrorActivityId() > 0) {
206                            SocialActivity mirrorActivity = null;
207    
208                            try {
209                                    mirrorActivity = socialActivityLocalService.getActivity(
210                                            activity.getMirrorActivityId());
211                            }
212                            catch (Exception e) {
213                            }
214    
215                            if (mirrorActivity != null) {
216                                    activity = mirrorActivity;
217                            }
218                    }
219    
220                    List<SocialActivityInterpreter> activityInterpreters =
221                            _activityInterpreters.get(selector);
222    
223                    if (activityInterpreters == null) {
224                            return null;
225                    }
226    
227                    String className = PortalUtil.getClassName(activity.getClassNameId());
228    
229                    for (int i = 0; i < activityInterpreters.size(); i++) {
230                            SocialActivityInterpreterImpl activityInterpreter =
231                                    (SocialActivityInterpreterImpl)activityInterpreters.get(i);
232    
233                            if (activityInterpreter.hasClassName(className)) {
234                                    SocialActivityFeedEntry activityFeedEntry =
235                                            activityInterpreter.interpret(activity, serviceContext);
236    
237                                    if (activityFeedEntry != null) {
238                                            activityFeedEntry.setPortletId(
239                                                    activityInterpreter.getPortletId());
240    
241                                            return activityFeedEntry;
242                                    }
243                            }
244                    }
245    
246                    return null;
247            }
248    
249            @Override
250            public SocialActivityFeedEntry interpret(
251                    String selector, SocialActivitySet activitySet,
252                    ServiceContext serviceContext) {
253    
254                    HttpServletRequest request = serviceContext.getRequest();
255    
256                    if (request == null) {
257                            return null;
258                    }
259    
260                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
261                            WebKeys.THEME_DISPLAY);
262    
263                    try {
264                            if (activitySet.getUserId() == themeDisplay.getDefaultUserId()) {
265                                    return null;
266                            }
267                    }
268                    catch (Exception e) {
269                            _log.error(e, e);
270                    }
271    
272                    List<SocialActivityInterpreter> activityInterpreters =
273                            _activityInterpreters.get(selector);
274    
275                    if (activityInterpreters == null) {
276                            return null;
277                    }
278    
279                    String className = PortalUtil.getClassName(
280                            activitySet.getClassNameId());
281    
282                    for (int i = 0; i < activityInterpreters.size(); i++) {
283                            SocialActivityInterpreterImpl activityInterpreter =
284                                    (SocialActivityInterpreterImpl)activityInterpreters.get(i);
285    
286                            if (activityInterpreter.hasClassName(className)) {
287                                    SocialActivityFeedEntry activityFeedEntry =
288                                            activityInterpreter.interpret(activitySet, serviceContext);
289    
290                                    if (activityFeedEntry != null) {
291                                            activityFeedEntry.setPortletId(
292                                                    activityInterpreter.getPortletId());
293    
294                                            return activityFeedEntry;
295                                    }
296                            }
297                    }
298    
299                    return null;
300            }
301    
302            @Override
303            public void updateActivitySet(long activityId) throws PortalException {
304                    if (!PropsValues.SOCIAL_ACTIVITY_SETS_BUNDLING_ENABLED) {
305                            socialActivitySetLocalService.addActivitySet(activityId);
306    
307                            return;
308                    }
309    
310                    List<SocialActivityInterpreter> activityInterpreters =
311                            _activityInterpreters.get(
312                                    PropsValues.SOCIAL_ACTIVITY_SETS_SELECTOR);
313    
314                    if (activityInterpreters != null) {
315                            SocialActivity activity =
316                                    socialActivityPersistence.findByPrimaryKey(activityId);
317    
318                            String className = PortalUtil.getClassName(
319                                    activity.getClassNameId());
320    
321                            for (int i = 0; i < activityInterpreters.size(); i++) {
322                                    SocialActivityInterpreterImpl activityInterpreter =
323                                            (SocialActivityInterpreterImpl)activityInterpreters.get(i);
324    
325                                    if (activityInterpreter.hasClassName(className)) {
326                                            activityInterpreter.updateActivitySet(activityId);
327    
328                                            return;
329                                    }
330                            }
331                    }
332            }
333    
334            private static final Log _log = LogFactoryUtil.getLog(
335                    SocialActivityInterpreterLocalServiceImpl.class);
336    
337            private final Map<String, List<SocialActivityInterpreter>>
338                    _activityInterpreters = new HashMap<>();
339            private final ServiceRegistrationMap<SocialActivityInterpreter>
340                    _serviceRegistrations = new ServiceRegistrationMapImpl<>();
341            private ServiceTracker<SocialActivityInterpreter, SocialActivityInterpreter>
342                    _serviceTracker;
343    
344            private class SocialActivityInterpreterServiceTrackerCustomizer
345                    implements ServiceTrackerCustomizer
346                            <SocialActivityInterpreter, SocialActivityInterpreter> {
347    
348                    @Override
349                    public SocialActivityInterpreter addingService(
350                            ServiceReference<SocialActivityInterpreter> serviceReference) {
351    
352                            Registry registry = RegistryUtil.getRegistry();
353    
354                            SocialActivityInterpreter activityInterpreter = registry.getService(
355                                    serviceReference);
356    
357                            String portletId = (String)serviceReference.getProperty(
358                                    "javax.portlet.name");
359    
360                            if (!(activityInterpreter instanceof
361                                            SocialRequestInterpreterImpl)) {
362    
363                                    activityInterpreter = new SocialActivityInterpreterImpl(
364                                            portletId, activityInterpreter);
365                            }
366    
367                            List<SocialActivityInterpreter> activityInterpreters =
368                                    _activityInterpreters.get(activityInterpreter.getSelector());
369    
370                            if (activityInterpreters == null) {
371                                    activityInterpreters = new ArrayList<>();
372                            }
373    
374                            activityInterpreters.add(activityInterpreter);
375    
376                            _activityInterpreters.put(
377                                    activityInterpreter.getSelector(), activityInterpreters);
378    
379                            return activityInterpreter;
380                    }
381    
382                    @Override
383                    public void modifiedService(
384                            ServiceReference<SocialActivityInterpreter> serviceReference,
385                            SocialActivityInterpreter activityInterpreter) {
386                    }
387    
388                    @Override
389                    public void removedService(
390                            ServiceReference<SocialActivityInterpreter> serviceReference,
391                            SocialActivityInterpreter activityInterpreter) {
392    
393                            Registry registry = RegistryUtil.getRegistry();
394    
395                            registry.ungetService(serviceReference);
396    
397                            List<SocialActivityInterpreter> activityInterpreters =
398                                    _activityInterpreters.get(activityInterpreter.getSelector());
399    
400                            if (activityInterpreters == null) {
401                                    return;
402                            }
403    
404                            activityInterpreters.remove(activityInterpreter);
405                    }
406    
407            }
408    
409    }