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