001    /**
002     * Copyright (c) 2000-2013 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.exception.SystemException;
019    import com.liferay.portal.model.User;
020    import com.liferay.portlet.social.RelationUserIdException;
021    import com.liferay.portlet.social.model.SocialRelation;
022    import com.liferay.portlet.social.model.SocialRelationConstants;
023    import com.liferay.portlet.social.service.base.SocialRelationLocalServiceBaseImpl;
024    
025    import java.util.List;
026    
027    /**
028     * The social relation local service. This service provides methods to handle
029     * unidirectional or bidirectional relations between users.
030     *
031     * <p>
032     * Relations between users can be unidirectional or bidirectional. The type of
033     * relation is determined by an integer constant. Some example relations are
034     * <i>co-worker, friend, romantic partner, sibling, spouse, child, enemy,
035     * follower, parent, subordinate, supervisor</i>.
036     * </p>
037     *
038     * <p>
039     * The two users participating in the relation are designated as User1 and
040     * User2. In case of unidirectional relations User1 should always be the subject
041     * of the relation. You can use the following English sentence to find out which
042     * user to use as User1 and which to use as User2:
043     * </p>
044     *
045     * <p>
046     * User1 is <i>&lt;relation&gt;</i> of User2 (e.g. User1 is parent of User2;
047     * User1 is supervisor of User2)
048     * </p>
049     *
050     * <p>
051     * For bidirectional relations, the service automatically generates the inverse
052     * relation.
053     * </p>
054     *
055     * @author Brian Wing Shun Chan
056     */
057    public class SocialRelationLocalServiceImpl
058            extends SocialRelationLocalServiceBaseImpl {
059    
060            /**
061             * Adds a social relation between the two users to the database.
062             *
063             * @param  userId1 the user that is the subject of the relation
064             * @param  userId2 the user at the other end of the relation
065             * @param  type the type of the relation
066             * @return the social relation
067             * @throws PortalException if the users could not be found, if the users
068             *         were not from the same company, or if either of the users was the
069             *         default user
070             * @throws SystemException if a system exception occurred
071             */
072            @Override
073            public SocialRelation addRelation(long userId1, long userId2, int type)
074                    throws PortalException, SystemException {
075    
076                    if (userId1 == userId2) {
077                            throw new RelationUserIdException();
078                    }
079    
080                    User user1 = userPersistence.findByPrimaryKey(userId1);
081                    User user2 = userPersistence.findByPrimaryKey(userId2);
082    
083                    if (user1.getCompanyId() != user2.getCompanyId()) {
084                            throw new RelationUserIdException();
085                    }
086    
087                    SocialRelation relation = socialRelationPersistence.fetchByU1_U2_T(
088                            userId1, userId2, type);
089    
090                    if (relation == null) {
091                            long relationId = counterLocalService.increment();
092    
093                            relation = socialRelationPersistence.create(relationId);
094    
095                            relation.setCompanyId(user1.getCompanyId());
096                            relation.setCreateDate(System.currentTimeMillis());
097                            relation.setUserId1(userId1);
098                            relation.setUserId2(userId2);
099                            relation.setType(type);
100    
101                            socialRelationPersistence.update(relation, false);
102                    }
103    
104                    if (SocialRelationConstants.isTypeBi(type)) {
105                            SocialRelation biRelation =
106                                    socialRelationPersistence.fetchByU1_U2_T(
107                                            userId2, userId1, type);
108    
109                            if (biRelation == null) {
110                                    long biRelationId = counterLocalService.increment();
111    
112                                    biRelation = socialRelationPersistence.create(biRelationId);
113    
114                                    biRelation.setCompanyId(user1.getCompanyId());
115                                    biRelation.setCreateDate(System.currentTimeMillis());
116                                    biRelation.setUserId1(userId2);
117                                    biRelation.setUserId2(userId1);
118                                    biRelation.setType(type);
119    
120                                    socialRelationPersistence.update(biRelation, false);
121                            }
122                    }
123    
124                    return relation;
125            }
126    
127            /**
128             * Removes the relation (and its inverse in case of a bidirectional
129             * relation) from the database.
130             *
131             * @param  relationId the primary key of the relation
132             * @throws PortalException if the relation could not be found
133             * @throws SystemException if a system exception occurred
134             */
135            @Override
136            public void deleteRelation(long relationId)
137                    throws PortalException, SystemException {
138    
139                    SocialRelation relation = socialRelationPersistence.findByPrimaryKey(
140                            relationId);
141    
142                    deleteRelation(relation);
143            }
144    
145            /**
146             * Removes the matching relation (and its inverse in case of a bidirectional
147             * relation) from the database.
148             *
149             * @param  userId1 the user that is the subject of the relation
150             * @param  userId2 the user at the other end of the relation
151             * @param  type the relation's type
152             * @throws PortalException if the relation or its inverse relation (if
153             *         applicable) could not be found
154             * @throws SystemException if a system exception occurred
155             */
156            @Override
157            public void deleteRelation(long userId1, long userId2, int type)
158                    throws PortalException, SystemException {
159    
160                    SocialRelation relation = socialRelationPersistence.findByU1_U2_T(
161                            userId1, userId2, type);
162    
163                    deleteRelation(relation);
164            }
165    
166            /**
167             * Removes the relation (and its inverse in case of a bidirectional
168             * relation) from the database.
169             *
170             * @param  relation the relation to be removed
171             * @throws PortalException if the relation is bidirectional and its inverse
172             *         relation could not be found
173             * @throws SystemException if a system exception occurred
174             */
175            @Override
176            public void deleteRelation(SocialRelation relation)
177                    throws PortalException, SystemException {
178    
179                    socialRelationPersistence.remove(relation);
180    
181                    if (SocialRelationConstants.isTypeBi(relation.getType())) {
182                            SocialRelation biRelation = socialRelationPersistence.findByU1_U2_T(
183                                    relation.getUserId2(), relation.getUserId1(),
184                                    relation.getType());
185    
186                            socialRelationPersistence.remove(biRelation);
187                    }
188            }
189    
190            /**
191             * Removes all relations involving the user from the database.
192             *
193             * @param  userId the primary key of the user
194             * @throws SystemException if a system exception occurred
195             */
196            @Override
197            public void deleteRelations(long userId) throws SystemException {
198                    socialRelationPersistence.removeByUserId1(userId);
199                    socialRelationPersistence.removeByUserId2(userId);
200            }
201    
202            /**
203             * Removes all relations between User1 and User2.
204             *
205             * @param  userId1 the user that is the subject of the relation
206             * @param  userId2 the user at the other end of the relation
207             * @throws PortalException if the inverse relation could not be found
208             * @throws SystemException if a system exception occurred
209             */
210            @Override
211            public void deleteRelations(long userId1, long userId2)
212                    throws PortalException, SystemException {
213    
214                    List<SocialRelation> relations = socialRelationPersistence.findByU1_U2(
215                            userId1, userId2);
216    
217                    for (SocialRelation relation : relations) {
218                            deleteRelation(relation);
219                    }
220            }
221    
222            /**
223             * Returns a range of all the inverse relations of the given type for which
224             * the user is User2 of the relation.
225             *
226             * <p>
227             * Useful when paginating results. Returns a maximum of <code>end -
228             * start</code> instances. <code>start</code> and <code>end</code> are not
229             * primary keys, they are indexes in the result set. Thus, <code>0</code>
230             * refers to the first result in the set. Setting both <code>start</code>
231             * and <code>end</code> to {@link
232             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
233             * result set.
234             * </p>
235             *
236             * @param  userId the primary key of the user
237             * @param  type the relation's type
238             * @param  start the lower bound of the range of results
239             * @param  end the upper bound of the range of results (not inclusive)
240             * @return the range of matching relations
241             * @throws SystemException if a system exception occurred
242             */
243            @Override
244            public List<SocialRelation> getInverseRelations(
245                            long userId, int type, int start, int end)
246                    throws SystemException {
247    
248                    return socialRelationPersistence.findByU2_T(userId, type, start, end);
249            }
250    
251            /**
252             * Returns the number of inverse relations of the given type for which the
253             * user is User2 of the relation.
254             *
255             * @param  userId the primary key of the user
256             * @param  type the relation's type
257             * @return the number of matching relations
258             * @throws SystemException if a system exception occurred
259             */
260            @Override
261            public int getInverseRelationsCount(long userId, int type)
262                    throws SystemException {
263    
264                    return socialRelationPersistence.countByU2_T(userId, type);
265            }
266    
267            /**
268             * Returns the relation identified by its primary key.
269             *
270             * @param  relationId the primary key of the relation
271             * @return Returns the relation
272             * @throws PortalException if the relation could not be found
273             * @throws SystemException if a system exception occurred
274             */
275            @Override
276            public SocialRelation getRelation(long relationId)
277                    throws PortalException, SystemException {
278    
279                    return socialRelationPersistence.findByPrimaryKey(relationId);
280            }
281    
282            /**
283             * Returns the relation of the given type between User1 and User2.
284             *
285             * @param  userId1 the user that is the subject of the relation
286             * @param  userId2 the user at the other end of the relation
287             * @param  type the relation's type
288             * @return Returns the relation
289             * @throws PortalException if the relation could not be found
290             * @throws SystemException if a system exception occurred
291             */
292            @Override
293            public SocialRelation getRelation(long userId1, long userId2, int type)
294                    throws PortalException, SystemException {
295    
296                    return socialRelationPersistence.findByU1_U2_T(userId1, userId2, type);
297            }
298    
299            /**
300             * Returns a range of all the relations of the given type where the user is
301             * the subject of the relation.
302             *
303             * <p>
304             * Useful when paginating results. Returns a maximum of <code>end -
305             * start</code> instances. <code>start</code> and <code>end</code> are not
306             * primary keys, they are indexes in the result set. Thus, <code>0</code>
307             * refers to the first result in the set. Setting both <code>start</code>
308             * and <code>end</code> to {@link
309             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
310             * result set.
311             * </p>
312             *
313             * @param  userId the primary key of the user
314             * @param  type the relation's type
315             * @param  start the lower bound of the range of results
316             * @param  end the upper bound of the range of results (not inclusive)
317             * @return the range of relations
318             * @throws SystemException if a system exception occurred
319             */
320            @Override
321            public List<SocialRelation> getRelations(
322                            long userId, int type, int start, int end)
323                    throws SystemException {
324    
325                    return socialRelationPersistence.findByU1_T(userId, type, start, end);
326            }
327    
328            /**
329             * Returns a range of all the relations between User1 and User2.
330             *
331             * <p>
332             * Useful when paginating results. Returns a maximum of <code>end -
333             * start</code> instances. <code>start</code> and <code>end</code> are not
334             * primary keys, they are indexes in the result set. Thus, <code>0</code>
335             * refers to the first result in the set. Setting both <code>start</code>
336             * and <code>end</code> to {@link
337             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
338             * result set.
339             * </p>
340             *
341             * @param  userId1 the user that is the subject of the relation
342             * @param  userId2 the user at the other end of the relation
343             * @param  start the lower bound of the range of results
344             * @param  end the upper bound of the range of results (not inclusive)
345             * @return the range of relations
346             * @throws SystemException if a system exception occurred
347             */
348            @Override
349            public List<SocialRelation> getRelations(
350                            long userId1, long userId2, int start, int end)
351                    throws SystemException {
352    
353                    return socialRelationPersistence.findByU1_U2(
354                            userId1, userId2, start, end);
355            }
356    
357            /**
358             * Returns the number of relations of the given type where the user is the
359             * subject of the relation.
360             *
361             * @param  userId the primary key of the user
362             * @param  type the relation's type
363             * @return the number of relations
364             * @throws SystemException if a system exception occurred
365             */
366            @Override
367            public int getRelationsCount(long userId, int type) throws SystemException {
368                    return socialRelationPersistence.countByU1_T(userId, type);
369            }
370    
371            /**
372             * Returns the number of relations between User1 and User2.
373             *
374             * @param  userId1 the user that is the subject of the relation
375             * @param  userId2 the user at the other end of the relation
376             * @return the number of relations
377             * @throws SystemException if a system exception occurred
378             */
379            @Override
380            public int getRelationsCount(long userId1, long userId2)
381                    throws SystemException {
382    
383                    return socialRelationPersistence.countByU1_U2(userId1, userId2);
384            }
385    
386            /**
387             * Returns <code>true</code> if a relation of the given type exists where
388             * the user with primary key <code>userId1</code> is User1 of the relation
389             * and the user with the primary key <code>userId2</code> is User2 of the
390             * relation.
391             *
392             * @param  userId1 the user that is the subject of the relation
393             * @param  userId2 the user at the other end of the relation
394             * @param  type the relation's type
395             * @return <code>true</code> if the relation exists; <code>false</code>
396             *         otherwise
397             * @throws SystemException if a system exception occurred
398             */
399            @Override
400            public boolean hasRelation(long userId1, long userId2, int type)
401                    throws SystemException {
402    
403                    SocialRelation relation = socialRelationPersistence.fetchByU1_U2_T(
404                            userId1, userId2, type);
405    
406                    if (relation == null) {
407                            return false;
408                    }
409                    else {
410                            return true;
411                    }
412            }
413    
414            /**
415             * Returns <code>true</code> if the users can be in a relation of the given
416             * type where the user with primary key <code>userId1</code> is User1 of the
417             * relation and the user with the primary key <code>userId2</code> is User2
418             * of the relation.
419             *
420             * <p>
421             * This method returns <code>false</code> if User1 and User2 are the same,
422             * if either user is the default user, or if a matching relation already
423             * exists.
424             * </p>
425             *
426             * @param  userId1 the user that is the subject of the relation
427             * @param  userId2 the user at the other end of the relation
428             * @param  type the relation's type
429             * @return <code>true</code> if the two users can be in a new relation of
430             *         the given type; <code>false</code> otherwise
431             * @throws SystemException if a system exception occurred
432             */
433            @Override
434            public boolean isRelatable(long userId1, long userId2, int type)
435                    throws SystemException {
436    
437                    if (userId1 == userId2) {
438                            return false;
439                    }
440    
441                    User user1 = userPersistence.fetchByPrimaryKey(userId1);
442    
443                    if ((user1 == null) || user1.isDefaultUser()) {
444                            return false;
445                    }
446    
447                    User user2 = userPersistence.fetchByPrimaryKey(userId2);
448    
449                    if ((user2 == null) || user2.isDefaultUser()) {
450                            return false;
451                    }
452    
453                    return !hasRelation(userId1, userId2, type);
454            }
455    
456    }