/** * Yobi, Project Hosting SW * * Copyright 2013 NAVER Corp. * http://yobi.io * * @author Yi EungJun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package models; import com.avaje.ebean.annotation.Transactional; import controllers.UserApp; import models.enumeration.Operation; import models.enumeration.ResourceType; import models.resource.GlobalResource; import models.resource.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.Predicate; import utils.AccessControl; import javax.persistence.Entity; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @Entity public class Watch extends UserAction { private static final long serialVersionUID = 1L; public static final Finder<Long, Watch> find = new Finder<>(Long.class, Watch.class); public static List<Watch> findBy(ResourceType resourceType, String resourceId) { return findBy(find, resourceType, resourceId); } public static Watch findBy(User watcher, ResourceType resourceType, String resourceId) { return findBy(find, watcher, resourceType, resourceId); } public static List<Watch> findBy(User user, ResourceType resourceType) { return findBy(find, user, resourceType); } public static int countBy(ResourceType type, String id) { return countBy(find, type, id); } public static void watch(Resource resource) { watch(UserApp.currentUser(), resource); } @Transactional public static void watch(User user, Resource resource) { watch(user, resource.getType(), resource.getId()); } public static void watch(User user, ResourceType resourceType, String resourceId) { Watch watch = Watch.findBy(user, resourceType, resourceId); if (watch == null) { watch = new Watch(); watch.user = user; watch.resourceId = resourceId; watch.resourceType = resourceType; watch.save(); } Unwatch unwatch = Unwatch.findBy(user, resourceType, resourceId); if (unwatch != null) { unwatch.delete(); } } public static void unwatch(Resource resource) { unwatch(UserApp.currentUser(), resource); } public static void unwatch(User user, Resource resource) { unwatch(user, resource.getType(), resource.getId()); } public static void unwatch(User user, ResourceType resourceType, String resourceId) { Unwatch unwatch = Unwatch.findBy(user, resourceType, resourceId); if (unwatch == null) { unwatch = new Unwatch(); unwatch.user = user; unwatch.resourceId = resourceId; unwatch.resourceType = resourceType; unwatch.save(); } Watch watch = Watch.findBy(user, resourceType, resourceId); if (watch != null) { watch.delete(); } } public static Set<User> findWatchers(Resource target) { return findWatchers(target.getType(), target.getId()); } public static Set<User> findWatchers(ResourceType resourceType, String resourceId) { HashSet<User> users = new HashSet<>(); for (Watch watch: Watch.findBy(resourceType, resourceId)) { users.add(watch.user); } return users; } public static Set<User> findUnwatchers(Resource target) { return findUnwatchers(target.getType(), target.getId()); } public static Set<User> findUnwatchers(ResourceType resourceType, String resourceId) { HashSet<User> users = new HashSet<>(); for (Unwatch unwatch: Unwatch.findBy(resourceType, resourceId)) { users.add(unwatch.user); } return users; } public static List<String> findWatchedResourceIds(User user, ResourceType resourceType) { ArrayList<String> resourceIds = new ArrayList<>(); for (Watch watch: Watch.findBy(user, resourceType)) { resourceIds.add(watch.resourceId); } for (Unwatch unwatch: Unwatch.findBy(user, resourceType)) { resourceIds.remove(unwatch.resourceId); } return resourceIds; } public static boolean isWatching(User user, ResourceType resourceType, String resourceId) { Watch watch = Watch.findBy(user, resourceType, resourceId); Unwatch unwatch = Unwatch.findBy(user, resourceType, resourceId); return watch != null && unwatch == null; } public static boolean isWatching(User user, Resource resource) { return isWatching(user, resource.getType(), resource.getId()); } public static boolean isWatching(Resource resource) { return isWatching(UserApp.currentUser(), resource.getType(), resource.getId()); } public static Set<User> findActualWatchers(final Set<User> baseWatchers, final Resource resource) { Set<User> actualWatchers = new HashSet<>(); actualWatchers.addAll(baseWatchers); // Add every user who watches the project to which this resource belongs if (!(resource instanceof GlobalResource)) { Project project = resource.getProject(); actualWatchers.addAll(findWatchers(project.asResource())); } // For this resource, add every user who watch explicitly and remove who unwatch explicitly. actualWatchers.addAll(findWatchers(resource)); actualWatchers.removeAll(findUnwatchers(resource)); // Filter the watchers who has no permission to read this resource. CollectionUtils.filter(actualWatchers, new Predicate() { @Override public boolean evaluate(Object watcher) { return AccessControl.isAllowed((User) watcher, resource, Operation.READ); } }); return actualWatchers; } }