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