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.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.ListUtil;
021    import com.liferay.portal.kernel.util.ProxyFactory;
022    import com.liferay.portal.kernel.util.Tuple;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.kernel.xml.Document;
025    import com.liferay.portal.kernel.xml.DocumentException;
026    import com.liferay.portal.kernel.xml.DocumentType;
027    import com.liferay.portal.kernel.xml.Element;
028    import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
029    import com.liferay.portal.util.JavaFieldsParser;
030    import com.liferay.social.kernel.model.SocialAchievement;
031    import com.liferay.social.kernel.model.SocialActivityCounterConstants;
032    import com.liferay.social.kernel.model.SocialActivityCounterDefinition;
033    import com.liferay.social.kernel.model.SocialActivityDefinition;
034    import com.liferay.social.kernel.model.SocialActivityProcessor;
035    import com.liferay.social.kernel.util.SocialConfiguration;
036    
037    import java.util.ArrayList;
038    import java.util.Collections;
039    import java.util.HashMap;
040    import java.util.LinkedHashSet;
041    import java.util.List;
042    import java.util.Map;
043    import java.util.Set;
044    
045    /**
046     * @author Zsolt Berentey
047     */
048    public class SocialConfigurationImpl implements SocialConfiguration {
049    
050            @Override
051            public List<String> getActivityCounterNames() {
052                    return getActivityCounterNames(
053                            SocialActivityCounterConstants.TYPE_ALL, false);
054            }
055    
056            @Override
057            public List<String> getActivityCounterNames(boolean transientCounter) {
058                    return getActivityCounterNames(
059                            SocialActivityCounterConstants.TYPE_ALL, transientCounter);
060            }
061    
062            @Override
063            public List<String> getActivityCounterNames(int ownerType) {
064                    return getActivityCounterNames(ownerType, false);
065            }
066    
067            @Override
068            public List<String> getActivityCounterNames(
069                    int ownerType, boolean transientCounter) {
070    
071                    Set<String> activityCounterNames = new LinkedHashSet<>();
072    
073                    for (Map<Integer, SocialActivityDefinition> activityDefinitions :
074                                    _activityDefinitions.values()) {
075    
076                            for (SocialActivityDefinition activityDefinition :
077                                            activityDefinitions.values()) {
078    
079                                    for (SocialActivityCounterDefinition activityCounterDefinition :
080                                                    activityDefinition.getActivityCounterDefinitions()) {
081    
082                                            if ((activityCounterDefinition.isTransient() ==
083                                                            transientCounter) &&
084                                                    ((ownerType ==
085                                                            SocialActivityCounterConstants.TYPE_ALL) ||
086                                                     (ownerType ==
087                                                             activityCounterDefinition.getOwnerType()))) {
088    
089                                                    activityCounterNames.add(
090                                                            activityCounterDefinition.getName());
091                                            }
092                                    }
093                            }
094                    }
095    
096                    return new ArrayList<>(activityCounterNames);
097            }
098    
099            @Override
100            public SocialActivityDefinition getActivityDefinition(
101                    String modelName, int activityType) {
102    
103                    Map<Integer, SocialActivityDefinition> activityDefinitions =
104                            _activityDefinitions.get(modelName);
105    
106                    if (activityDefinitions == null) {
107                            return null;
108                    }
109    
110                    return activityDefinitions.get(activityType);
111            }
112    
113            @Override
114            public List<SocialActivityDefinition> getActivityDefinitions(
115                    String modelName) {
116    
117                    Map<Integer, SocialActivityDefinition> activityDefinitions =
118                            _activityDefinitions.get(modelName);
119    
120                    if (activityDefinitions == null) {
121                            return Collections.emptyList();
122                    }
123    
124                    return ListUtil.fromCollection(activityDefinitions.values());
125            }
126    
127            @Override
128            public String[] getActivityModelNames() {
129                    Set<String> activityModelNames = _activityDefinitions.keySet();
130    
131                    return activityModelNames.toArray(
132                            new String[activityModelNames.size()]);
133            }
134    
135            @Override
136            public List<Object> read(ClassLoader classLoader, String[] xmls)
137                    throws Exception {
138    
139                    List<Object> objects = new ArrayList<>();
140    
141                    for (String xml : xmls) {
142                            _read(classLoader, xml, objects);
143                    }
144    
145                    return objects;
146            }
147    
148            @Override
149            public void removeActivityDefinition(
150                    SocialActivityDefinition activityDefinition) {
151    
152                    Map<Integer, SocialActivityDefinition> activityDefinitions =
153                            _activityDefinitions.get(activityDefinition.getModelName());
154    
155                    if (activityDefinitions != null) {
156                            activityDefinitions.remove(activityDefinition.getActivityType());
157                    }
158            }
159    
160            private void _read(
161                            ClassLoader classLoader, String xml, List<Object> objects)
162                    throws Exception {
163    
164                    if (xml == null) {
165                            return;
166                    }
167    
168                    xml = JavaFieldsParser.parse(classLoader, xml);
169    
170                    Document document = UnsecureSAXReaderUtil.read(xml);
171    
172                    DocumentType documentType = document.getDocumentType();
173    
174                    String publicId = documentType.getPublicId();
175    
176                    if (!publicId.equals("-//Liferay//DTD Social 6.1.0//EN") &&
177                            !publicId.equals("-//Liferay//DTD Social 6.2.0//EN") &&
178                            !publicId.equals("-//Liferay//DTD Social 7.0.0//EN")) {
179    
180                            throw new DocumentException(
181                                    "Unsupported document type " + publicId);
182                    }
183    
184                    Element rootElement = document.getRootElement();
185    
186                    List<Element> activityElements = rootElement.elements("activity");
187    
188                    for (Element activityElement : activityElements) {
189                            _readActivity(classLoader, objects, activityElement);
190                    }
191            }
192    
193            private void _readAchievement(
194                            ClassLoader classLoader, List<Object> objects,
195                            SocialActivityDefinition activityDefinition,
196                            Element achievementElement)
197                    throws Exception {
198    
199                    String achievementClassName = GetterUtil.getString(
200                            achievementElement.elementText("achievement-class"));
201    
202                    SocialAchievement achievement =
203                            (SocialAchievement)ProxyFactory.newInstance(
204                                    classLoader, SocialAchievement.class, achievementClassName);
205    
206                    String name = GetterUtil.getString(
207                            achievementElement.elementText("name"));
208    
209                    achievement.setName(name);
210    
211                    String icon = GetterUtil.getString(
212                            achievementElement.elementText("icon"));
213    
214                    achievement.setIcon(icon);
215    
216                    List<Element> propertyElements = achievementElement.elements(
217                            "property");
218    
219                    for (Element propertyElement : propertyElements) {
220                            _readAchievementProperty(achievement, propertyElement);
221                    }
222    
223                    achievement.initialize(activityDefinition);
224    
225                    List<SocialAchievement> achievements =
226                            activityDefinition.getAchievements();
227    
228                    achievements.add(achievement);
229    
230                    Tuple tuple = new Tuple(activityDefinition, achievement);
231    
232                    objects.add(tuple);
233            }
234    
235            private void _readAchievementProperty(
236                    SocialAchievement achievement, Element propertyElement) {
237    
238                    String name = GetterUtil.getString(propertyElement.elementText("name"));
239                    String value = GetterUtil.getString(
240                            propertyElement.elementText("value"));
241    
242                    achievement.setProperty(name, value);
243            }
244    
245            private void _readActivity(
246                            ClassLoader classLoader, Element activityElement,
247                            SocialActivityDefinition activityDefinition)
248                    throws Exception {
249    
250                    boolean logActivity = GetterUtil.getBoolean(
251                            activityElement.elementText("log-activity"));
252    
253                    activityDefinition.setLogActivity(logActivity);
254    
255                    boolean countersEnabled = GetterUtil.getBoolean(
256                            activityElement.elementText("counters-enabled"), true);
257    
258                    activityDefinition.setCountersEnabled(countersEnabled);
259    
260                    if (!countersEnabled) {
261                            return;
262                    }
263    
264                    String languageKey = GetterUtil.getString(
265                            activityElement.elementText("language-key"));
266    
267                    activityDefinition.setLanguageKey(languageKey);
268    
269                    String processorClassName = GetterUtil.getString(
270                            activityElement.elementText("processor-class"));
271    
272                    if (Validator.isNotNull(processorClassName)) {
273                            SocialActivityProcessor activityProcessor =
274                                    (SocialActivityProcessor)ProxyFactory.newInstance(
275                                            classLoader, SocialActivityProcessor.class,
276                                            processorClassName);
277    
278                            activityDefinition.setActivityProcessor(activityProcessor);
279                    }
280    
281                    _readActivityContribution(activityElement, activityDefinition);
282                    _readActivityParticipation(activityElement, activityDefinition);
283            }
284    
285            private void _readActivity(
286                            ClassLoader classLoader, List<Object> objects,
287                            Element activityElement)
288                    throws Exception {
289    
290                    String modelName = GetterUtil.getString(
291                            activityElement.elementText("model-name"));
292    
293                    Map<Integer, SocialActivityDefinition> activityDefinitions =
294                            _activityDefinitions.get(modelName);
295    
296                    if (activityDefinitions == null) {
297                            activityDefinitions = new HashMap<>();
298    
299                            _activityDefinitions.put(modelName, activityDefinitions);
300                    }
301    
302                    int activityType = GetterUtil.getInteger(
303                            activityElement.elementText("activity-type"));
304    
305                    SocialActivityDefinition activityDefinition = activityDefinitions.get(
306                            activityType);
307    
308                    if (activityDefinition == null) {
309                            activityDefinition = new SocialActivityDefinition();
310    
311                            activityDefinition.setModelName(modelName);
312                            activityDefinition.setActivityType(activityType);
313    
314                            _readActivity(classLoader, activityElement, activityDefinition);
315    
316                            activityDefinitions.put(activityType, activityDefinition);
317    
318                            objects.add(activityDefinition);
319                    }
320    
321                    List<Element> counterElements = activityElement.elements("counter");
322    
323                    for (Element counterElement : counterElements) {
324                            _readCounter(objects, activityDefinition, counterElement);
325                    }
326    
327                    List<Element> achievementElements = activityElement.elements(
328                            "achievement");
329    
330                    for (Element achievementElement : achievementElements) {
331                            _readAchievement(
332                                    classLoader, objects, activityDefinition, achievementElement);
333                    }
334            }
335    
336            private void _readActivityContribution(
337                    Element activityElement, SocialActivityDefinition activityDefinition) {
338    
339                    Element contributionValueElement = activityElement.element(
340                            "contribution-value");
341                    Element contributionLimitElement = activityElement.element(
342                            "contribution-limit");
343    
344                    if ((contributionValueElement == null) &&
345                            (contributionLimitElement == null)) {
346    
347                            return;
348                    }
349    
350                    SocialActivityCounterDefinition activityCounterDefinition =
351                            new SocialActivityCounterDefinition();
352    
353                    activityCounterDefinition.setName(
354                            SocialActivityCounterConstants.NAME_CONTRIBUTION);
355                    activityCounterDefinition.setOwnerType(
356                            SocialActivityCounterConstants.TYPE_CREATOR);
357    
358                    int increment = 0;
359    
360                    if (contributionValueElement != null) {
361                            increment = GetterUtil.getInteger(
362                                    contributionValueElement.getText());
363                    }
364    
365                    activityCounterDefinition.setIncrement(increment);
366    
367                    if (contributionLimitElement != null) {
368                            String limitEnabled = contributionLimitElement.attributeValue(
369                                    "enabled");
370    
371                            if (Validator.isNotNull(limitEnabled)) {
372                                    activityCounterDefinition.setLimitEnabled(
373                                            GetterUtil.getBoolean(limitEnabled));
374                            }
375    
376                            String limitPeriod = contributionLimitElement.attributeValue(
377                                    "period");
378    
379                            if (Validator.isNotNull(limitPeriod)) {
380                                    activityCounterDefinition.setLimitPeriod(limitPeriod);
381                            }
382    
383                            int limitValue = GetterUtil.getInteger(
384                                    contributionLimitElement.getText());
385    
386                            activityCounterDefinition.setLimitValue(limitValue);
387                    }
388    
389                    activityDefinition.addCounter(activityCounterDefinition);
390    
391                    SocialActivityCounterDefinition popularityActivityCounterDefinition =
392                            new SocialActivityCounterDefinition();
393    
394                    popularityActivityCounterDefinition.setName(
395                            SocialActivityCounterConstants.NAME_POPULARITY);
396                    popularityActivityCounterDefinition.setOwnerType(
397                            SocialActivityCounterConstants.TYPE_ASSET);
398                    popularityActivityCounterDefinition.setIncrement(
399                            activityCounterDefinition.getIncrement());
400                    popularityActivityCounterDefinition.setLimitEnabled(
401                            activityCounterDefinition.isLimitEnabled());
402                    popularityActivityCounterDefinition.setLimitPeriod(
403                            activityCounterDefinition.getLimitPeriod());
404                    popularityActivityCounterDefinition.setLimitValue(
405                            activityCounterDefinition.getLimitValue());
406    
407                    activityDefinition.addCounter(popularityActivityCounterDefinition);
408            }
409    
410            private void _readActivityParticipation(
411                    Element activityElement, SocialActivityDefinition activityDefinition) {
412    
413                    Element participationValueElement = activityElement.element(
414                            "participation-value");
415                    Element participationLimitElement = activityElement.element(
416                            "participation-limit");
417    
418                    if ((participationValueElement == null) &&
419                            (participationLimitElement == null)) {
420    
421                            return;
422                    }
423    
424                    SocialActivityCounterDefinition activityCounterDefinition =
425                            new SocialActivityCounterDefinition();
426    
427                    activityCounterDefinition.setName(
428                            SocialActivityCounterConstants.NAME_PARTICIPATION);
429                    activityCounterDefinition.setOwnerType(
430                            SocialActivityCounterConstants.TYPE_ACTOR);
431    
432                    int increment = 0;
433    
434                    if (participationValueElement != null) {
435                            increment = GetterUtil.getInteger(
436                                    participationValueElement.getText());
437                    }
438    
439                    activityCounterDefinition.setIncrement(increment);
440    
441                    if (participationLimitElement != null) {
442                            String limitEnabled = participationLimitElement.attributeValue(
443                                    "enabled");
444    
445                            if (Validator.isNotNull(limitEnabled)) {
446                                    activityCounterDefinition.setLimitEnabled(
447                                            GetterUtil.getBoolean(limitEnabled));
448                            }
449    
450                            String limitPeriod = participationLimitElement.attributeValue(
451                                    "period");
452    
453                            if (Validator.isNotNull(limitPeriod)) {
454                                    activityCounterDefinition.setLimitPeriod(limitPeriod);
455                            }
456    
457                            int limitValue = GetterUtil.getInteger(
458                                    participationLimitElement.getText());
459    
460                            activityCounterDefinition.setLimitValue(limitValue);
461                    }
462    
463                    activityDefinition.addCounter(activityCounterDefinition);
464            }
465    
466            private void _readCounter(
467                    List<Object> objects, SocialActivityDefinition activityDefinition,
468                    Element counterElement) {
469    
470                    SocialActivityCounterDefinition activityCounterDefinition =
471                            new SocialActivityCounterDefinition();
472    
473                    int increment = GetterUtil.getInteger(
474                            counterElement.elementText("increment"), 1);
475    
476                    activityCounterDefinition.setIncrement(increment);
477    
478                    boolean enabled = GetterUtil.getBoolean(
479                            counterElement.elementText("enabled"), true);
480    
481                    activityCounterDefinition.setEnabled(enabled);
482    
483                    String name = GetterUtil.getString(counterElement.elementText("name"));
484    
485                    activityCounterDefinition.setName(name);
486    
487                    String ownerType = GetterUtil.getString(
488                            counterElement.elementText("owner-type"));
489    
490                    activityCounterDefinition.setOwnerType(ownerType);
491    
492                    if (activityCounterDefinition.getOwnerType() == 0) {
493                            if (_log.isWarnEnabled()) {
494                                    _log.warn(
495                                            "Invalid owner type " + ownerType + " for model " +
496                                                    activityDefinition.getModelName());
497                            }
498    
499                            return;
500                    }
501    
502                    activityDefinition.addCounter(activityCounterDefinition);
503    
504                    Tuple tuple = new Tuple(activityDefinition, activityCounterDefinition);
505    
506                    objects.add(tuple);
507            }
508    
509            private static final Log _log = LogFactoryUtil.getLog(
510                    SocialConfigurationImpl.class);
511    
512            private final Map<String, Map<Integer, SocialActivityDefinition>>
513                    _activityDefinitions = new HashMap<>();
514    
515    }