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