Java tutorial
/** * * BibSonomy-Database - Database for BibSonomy. * * Copyright (C) 2006 - 2011 Knowledge & Data Engineering Group, * University of Kassel, Germany * http://www.kde.cs.uni-kassel.de/ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.bibsonomy.database; import static org.bibsonomy.util.ValidationUtils.present; import java.net.InetAddress; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.bibsonomy.common.enums.Classifier; import org.bibsonomy.common.enums.ClassifierSettings; import org.bibsonomy.common.enums.ConceptStatus; import org.bibsonomy.common.enums.ConceptUpdateOperation; import org.bibsonomy.common.enums.FilterEntity; import org.bibsonomy.common.enums.GroupID; import org.bibsonomy.common.enums.GroupUpdateOperation; import org.bibsonomy.common.enums.GroupingEntity; import org.bibsonomy.common.enums.HashID; import org.bibsonomy.common.enums.InetAddressStatus; import org.bibsonomy.common.enums.PostUpdateOperation; import org.bibsonomy.common.enums.Role; import org.bibsonomy.common.enums.SpamStatus; import org.bibsonomy.common.enums.StatisticsConstraint; import org.bibsonomy.common.enums.TagSimilarity; import org.bibsonomy.common.enums.UserRelation; import org.bibsonomy.common.enums.UserUpdateOperation; import org.bibsonomy.common.errors.UnspecifiedErrorMessage; import org.bibsonomy.common.exceptions.AccessDeniedException; import org.bibsonomy.common.exceptions.DatabaseException; import org.bibsonomy.common.exceptions.QueryTimeoutException; import org.bibsonomy.common.exceptions.ResourceMovedException; import org.bibsonomy.common.exceptions.ResourceNotFoundException; import org.bibsonomy.common.exceptions.SynchronizationRunningException; import org.bibsonomy.common.exceptions.UnsupportedResourceTypeException; import org.bibsonomy.common.exceptions.ValidationException; import org.bibsonomy.database.common.DBSession; import org.bibsonomy.database.common.DBSessionFactory; import org.bibsonomy.database.managers.AdminDatabaseManager; import org.bibsonomy.database.managers.AuthorDatabaseManager; import org.bibsonomy.database.managers.BasketDatabaseManager; import org.bibsonomy.database.managers.BibTexDatabaseManager; import org.bibsonomy.database.managers.BibTexExtraDatabaseManager; import org.bibsonomy.database.managers.BookmarkDatabaseManager; import org.bibsonomy.database.managers.CrudableContent; import org.bibsonomy.database.managers.DocumentDatabaseManager; import org.bibsonomy.database.managers.GoldStandardPublicationDatabaseManager; import org.bibsonomy.database.managers.GroupDatabaseManager; import org.bibsonomy.database.managers.InboxDatabaseManager; import org.bibsonomy.database.managers.PermissionDatabaseManager; import org.bibsonomy.database.managers.StatisticsDatabaseManager; import org.bibsonomy.database.managers.TagDatabaseManager; import org.bibsonomy.database.managers.TagRelationDatabaseManager; import org.bibsonomy.database.managers.UserDatabaseManager; import org.bibsonomy.database.managers.WikiDatabaseManager; import org.bibsonomy.database.managers.discussion.CommentDatabaseManager; import org.bibsonomy.database.managers.discussion.DiscussionDatabaseManager; import org.bibsonomy.database.managers.discussion.DiscussionItemDatabaseManager; import org.bibsonomy.database.managers.discussion.ReviewDatabaseManager; import org.bibsonomy.database.params.BibTexParam; import org.bibsonomy.database.params.BookmarkParam; import org.bibsonomy.database.params.GenericParam; import org.bibsonomy.database.params.StatisticsParam; import org.bibsonomy.database.params.TagParam; import org.bibsonomy.database.params.TagRelationParam; import org.bibsonomy.database.params.UserParam; import org.bibsonomy.database.systemstags.SystemTagsExtractor; import org.bibsonomy.database.systemstags.SystemTagsUtil; import org.bibsonomy.database.systemstags.search.SearchSystemTag; import org.bibsonomy.database.util.LogicInterfaceHelper; import org.bibsonomy.model.Author; import org.bibsonomy.model.BibTex; import org.bibsonomy.model.Bookmark; import org.bibsonomy.model.Comment; import org.bibsonomy.model.DiscussionItem; import org.bibsonomy.model.Document; import org.bibsonomy.model.GoldStandardPublication; import org.bibsonomy.model.Group; import org.bibsonomy.model.Post; import org.bibsonomy.model.Resource; import org.bibsonomy.model.Review; import org.bibsonomy.model.Tag; import org.bibsonomy.model.User; import org.bibsonomy.model.Wiki; import org.bibsonomy.model.enums.Order; import org.bibsonomy.model.extra.BibTexExtra; import org.bibsonomy.model.logic.LogicInterface; import org.bibsonomy.model.sync.ConflictResolutionStrategy; import org.bibsonomy.model.sync.SyncLogicInterface; import org.bibsonomy.model.sync.SyncService; import org.bibsonomy.model.sync.SynchronizationData; import org.bibsonomy.model.sync.SynchronizationDirection; import org.bibsonomy.model.sync.SynchronizationPost; import org.bibsonomy.model.sync.SynchronizationStatus; import org.bibsonomy.model.util.GroupUtils; import org.bibsonomy.model.util.PostUtils; import org.bibsonomy.model.util.UserUtils; import org.bibsonomy.sync.SynchronizationDatabaseManager; import org.bibsonomy.util.ObjectUtils; /** * Database Implementation of the LogicInterface * * @author Jens Illig * @author Christian Kramer * @author Christian Claus * @author Dominik Benz * @author Robert Jschke * * @version $Id: DBLogic.java,v 1.254 2011-07-26 15:34:32 rja Exp $ */ public class DBLogic implements LogicInterface, SyncLogicInterface { private static final Log log = LogFactory.getLog(DBLogic.class); /* * help maps for post managers and discussion managers */ private final Map<Class<? extends Resource>, CrudableContent<? extends Resource, ? extends GenericParam>> allDatabaseManagers; private final Map<Class<? extends DiscussionItem>, DiscussionItemDatabaseManager<? extends DiscussionItem>> allDiscussionManagers; private final AuthorDatabaseManager authorDBManager; private final DocumentDatabaseManager docDBManager; private final PermissionDatabaseManager permissionDBManager; private final BookmarkDatabaseManager bookmarkDBManager; private final BibTexDatabaseManager publicationDBManager; private final GoldStandardPublicationDatabaseManager goldStandardPublicationDBManager; private final BibTexExtraDatabaseManager bibTexExtraDBManager; private final DiscussionDatabaseManager discussionDatabaseManager; private final ReviewDatabaseManager reviewDBManager; private final CommentDatabaseManager commentDBManager; private final UserDatabaseManager userDBManager; private final GroupDatabaseManager groupDBManager; private final TagDatabaseManager tagDBManager; private final AdminDatabaseManager adminDBManager; private final DBSessionFactory dbSessionFactory; private final StatisticsDatabaseManager statisticsDBManager; private final TagRelationDatabaseManager tagRelationsDBManager; private final BasketDatabaseManager basketDBManager; private final InboxDatabaseManager inboxDBManager; private final WikiDatabaseManager wikiDBManager; private final SynchronizationDatabaseManager syncDBManager; private final User loginUser; /** * Returns an implementation of the DBLogic. * * @param loginUser * - the user which wants to use the logic. * @param dbSessionFactory */ protected DBLogic(final User loginUser, final DBSessionFactory dbSessionFactory) { this.loginUser = loginUser; this.allDatabaseManagers = new HashMap<Class<? extends Resource>, CrudableContent<? extends Resource, ? extends GenericParam>>(); // publication db manager this.publicationDBManager = BibTexDatabaseManager.getInstance(); this.allDatabaseManagers.put(BibTex.class, this.publicationDBManager); // bookmark db manager this.bookmarkDBManager = BookmarkDatabaseManager.getInstance(); this.allDatabaseManagers.put(Bookmark.class, this.bookmarkDBManager); // gold standard publication db manager this.goldStandardPublicationDBManager = GoldStandardPublicationDatabaseManager.getInstance(); this.allDatabaseManagers.put(GoldStandardPublication.class, this.goldStandardPublicationDBManager); // discussion and discussion item db manager this.commentDBManager = CommentDatabaseManager.getInstance(); this.reviewDBManager = ReviewDatabaseManager.getInstance(); this.discussionDatabaseManager = DiscussionDatabaseManager.getInstance(); this.allDiscussionManagers = new HashMap<Class<? extends DiscussionItem>, DiscussionItemDatabaseManager<? extends DiscussionItem>>(); this.allDiscussionManagers.put(Comment.class, this.commentDBManager); this.allDiscussionManagers.put(Review.class, this.reviewDBManager); this.authorDBManager = AuthorDatabaseManager.getInstance(); this.docDBManager = DocumentDatabaseManager.getInstance(); this.userDBManager = UserDatabaseManager.getInstance(); this.groupDBManager = GroupDatabaseManager.getInstance(); this.tagDBManager = TagDatabaseManager.getInstance(); this.adminDBManager = AdminDatabaseManager.getInstance(); this.permissionDBManager = PermissionDatabaseManager.getInstance(); this.statisticsDBManager = StatisticsDatabaseManager.getInstance(); this.tagRelationsDBManager = TagRelationDatabaseManager.getInstance(); this.basketDBManager = BasketDatabaseManager.getInstance(); this.inboxDBManager = InboxDatabaseManager.getInstance(); this.wikiDBManager = WikiDatabaseManager.getInstance(); this.syncDBManager = SynchronizationDatabaseManager.getInstance(); this.bibTexExtraDBManager = BibTexExtraDatabaseManager.getInstance(); this.dbSessionFactory = dbSessionFactory; } /** * Returns a new database session. If a user is logged in, he gets the * master connection, if not logged in, the secondary connection */ private DBSession openSession() { return this.dbSessionFactory.getDatabaseSession(); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getUserDetails(java.lang.String) * TODO: if userName = loginUser.getName() we could just return loginUser. */ @Override public User getUserDetails(final String userName) { final DBSession session = this.openSession(); try { /* * We don't use userName but user.getName() in the remaining part of * this method, since the name gets normalized in getUserDetails(). */ final User user = this.userDBManager.getUserDetails(userName, session); /* * only admin and myself may see which group I'm a member of */ if (this.permissionDBManager.isAdminOrSelf(this.loginUser, user.getName())) { user.setGroups(this.groupDBManager.getGroupsForUser(user.getName(), true, session)); // fill user's spam informations this.adminDBManager.getClassifierUserDetails(user, session); return user; } /* * respect user privacy settings * clear all profile attributes if current login user isn't allowed to see the profile */ if (!this.permissionDBManager.isAllowedToAccessUsersProfile(user, this.loginUser, session)) { /* * TODO: this practically clears /all/ user information */ return new User(user.getName()); } /* * clear the private stuff */ user.setEmail(null); user.setApiKey(null); user.setPassword(null); user.setReminderPassword(null); user.setReminderPasswordRequestDate(null); user.setSettings(null); /* * FIXME: other things set in userDBManager.getUserDetails() maybe not cleared! */ return user; } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#getSynchronization(java.lang.String, java.lang.Class, java.util.List, org.bibsonomy.model.sync.ConflictResolutionStrategy, java.lang.String) */ @Override public List<SynchronizationPost> getSyncPlan(final String userName, final URI service, final Class<? extends Resource> resourceType, final List<SynchronizationPost> clientPosts, final ConflictResolutionStrategy strategy, final SynchronizationDirection direction) { this.permissionDBManager.ensureWriteAccess(loginUser, userName); Date lastSuccessfulSyncDate = null; final Map<String, SynchronizationPost> serverPosts; final List<SynchronizationPost> posts; final DBSession session = this.openSession(); try { final SynchronizationData data = this.syncDBManager.getLastSyncData(userName, service, resourceType, null, session); /* * check for a running synchronization */ if (present(data) && SynchronizationStatus.RUNNING.equals(data.getStatus())) { // running synchronization // FIXME: if synchronization fails, we can't recover throw new SynchronizationRunningException(); } /* * check for last successful synchronization */ final SynchronizationData lsd = this.syncDBManager.getLastSyncData(userName, service, resourceType, SynchronizationStatus.DONE, session); if (present(lsd)) { lastSuccessfulSyncDate = lsd.getLastSyncDate(); } /* * flag synchronization as planned * FIXME: if the client is not in the sync_services table, this * statements silently fails. :-( */ this.syncDBManager.insertSynchronizationData(userName, service, resourceType, new Date(), SynchronizationStatus.PLANNED, session); /* * get posts from server (=this machine) */ if (BibTex.class.equals(resourceType)) { serverPosts = publicationDBManager.getSyncPostsMapForUser(userName, session); } else if (Bookmark.class.equals(resourceType)) { serverPosts = bookmarkDBManager.getSyncPostsMapForUser(userName, session); } else { throw new UnsupportedResourceTypeException(); } /* * if necessary, set the synchronization date to some distant old value */ if (!present(lastSuccessfulSyncDate)) { lastSuccessfulSyncDate = new Date(0); } /* * calculate synchronization plan */ posts = this.syncDBManager.getSyncPlan(serverPosts, clientPosts, lastSuccessfulSyncDate, strategy, direction); /* * attach "real" posts to the synchronization posts, which will be updated (or created) on the client */ for (final SynchronizationPost post : posts) { switch (post.getAction()) { case CREATE_CLIENT: case UPDATE_CLIENT: post.setPost(this.getPostDetails(post.getIntraHash(), userName)); break; default: break; } } } finally { session.close(); } return posts; } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#createSyncService() */ @Override public void createSyncService(final URI service, final boolean server) { this.permissionDBManager.ensureAdminAccess(loginUser); final DBSession session = this.openSession(); try { syncDBManager.createSyncService(session, service, server); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#deleteSyncService(java.net.URI, boolean) */ @Override public void deleteSyncService(final URI service, final boolean server) { this.permissionDBManager.ensureAdminAccess(loginUser); final DBSession session = this.openSession(); try { syncDBManager.deleteSyncService(session, service, server); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#createSyncServer(java.lang.String, int, java.util.Properties) */ @Override public void createSyncServer(final String userName, final URI service, final Class<? extends Resource> resourceType, final Properties userCredentials, final SynchronizationDirection direction, final ConflictResolutionStrategy strategy) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { syncDBManager.createSyncServerForUser(session, userName, service, resourceType, userCredentials, direction, strategy); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#updateSyncServer(java.lang.String, java.net.URI, java.util.Properties) */ @Override public void updateSyncServer(final String userName, final URI service, final Class<? extends Resource> resourceType, final Properties userCredentials, final SynchronizationDirection direction, final ConflictResolutionStrategy strategy) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { syncDBManager.updateSyncServerForUser(session, userName, service, resourceType, userCredentials, direction, strategy); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#deleteSyncServer(java.lang.String, java.net.URI) */ @Override public void deleteSyncServer(final String userName, final URI service) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { syncDBManager.deleteSyncServerForUser(session, userName, service); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#getSyncServerForUser(java.lang.String) */ @Override public List<SyncService> getSyncServer(final String userName) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { return syncDBManager.getSyncServersForUser(userName, session); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#getAvlSyncServer() */ @Override public List<URI> getSyncServices(final boolean server) { final DBSession session = this.openSession(); try { return syncDBManager.getSyncServices(session, server); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#getLastSynchronizationData(java.lang.String, int, int) */ @Override public SynchronizationData getLastSyncData(final String userName, final URI service, final Class<? extends Resource> resourceType) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { return syncDBManager.getLastSyncData(userName, service, resourceType, null, session); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#setCurrentSyncDone(org.bibsonomy.model.sync.SynchronizationData) */ @Override public void updateSyncData(final String userName, final URI service, final Class<? extends Resource> resourceType, final Date syncDate, final SynchronizationStatus status, final String info) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { syncDBManager.updateSyncData(session, userName, service, resourceType, syncDate, status, info); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#setCurrentSyncDone(org.bibsonomy.model.sync.SynchronizationData) */ @Override public void deleteSyncData(final String userName, final URI service, final Class<? extends Resource> resourceType, final Date syncDate) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { syncDBManager.deleteSyncData(session, userName, service, resourceType, syncDate); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.sync.SyncLogicInterface#getPostsForSync(java.lang.Class, java.lang.String) */ @Override public List<SynchronizationPost> getSyncPosts(final String userName, final Class<? extends Resource> resourceType) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = this.openSession(); try { if (resourceType == BibTex.class) { return this.publicationDBManager.getSyncPostsListForUser(userName, session); } else if (resourceType == Bookmark.class) { return this.bookmarkDBManager.getSyncPostsListForUser(userName, session); } else { throw new UnsupportedResourceTypeException(); } } finally { session.close(); } } /** * TODO: rename method doesn't validate anything * Method to handle privacy settings of posts for synchronization * @param post */ private void validateGroupsForSynchronization(final Post<? extends Resource> post) { /* * check if not public or private group */ if (!GroupUtils.containsExclusiveGroup(post.getGroups())) { /* * post has group -> change to private */ post.setGroups(Collections.singleton(GroupUtils.getPrivateGroup())); } /* * if public or private is nothing to do */ } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.PostLogicInterface#getPosts(java.lang.Class, * org.bibsonomy.common.enums.GroupingEntity, java.lang.String, * java.util.List, java.lang.String, org.bibsonomy.model.enums.Order, * org.bibsonomy.common.enums.FilterEntity, int, int, java.lang.String) */ @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public <T extends Resource> List<Post<T>> getPosts(final Class<T> resourceType, final GroupingEntity grouping, final String groupingName, final List<String> tags, final String hash, final Order order, final FilterEntity filter, final int start, final int end, final String search) { // check allowed start-/end-values if (GroupingEntity.ALL.equals(grouping) && !present(tags) && !present(search)) { this.permissionDBManager.checkStartEnd(loginUser, start, end, "post"); } // check maximum number of allowed tags if (this.permissionDBManager.exceedsMaxmimumSize(tags)) { return new ArrayList<Post<T>>(); } // check for systemTags disabling this resourceType if (!this.systemTagsAllowResourceType(tags, resourceType)) { return new ArrayList<Post<T>>(); } final DBSession session = this.openSession(); try { /* * if (resourceType == Resource.class) { yes, this IS unsave and * indeed it BREAKS restrictions on generic-constraints. it is the * result of two designs: 1. @ibatis: database-results should be * accessible as a stream or should at least be saved using the * visitor pattern (collection<? super X> arguments would do fine) * 2. @bibsonomy: this method needs runtime-type-checking which is * not supported by generics so what: copy each and every entry * manually or split this method to become type-safe WITHOUT falling * back to <? extends Resource> (which means read-only) in the whole * project result = bibtexDBManager.getPosts(authUser, grouping, * groupingName, tags, hash, popular, added, start, end, false); // * TODO: solve problem with limit+offset: * result.addAll(bookmarkDBManager.getPosts(authUser, grouping, * groupingName, tags, hash, popular, added, start, end, false)); * */ if (resourceType == BibTex.class) { final BibTexParam param = LogicInterfaceHelper.buildParam(BibTexParam.class, grouping, groupingName, tags, hash, order, start, end, search, filter, this.loginUser); // check permissions for displaying links to documents final boolean allowedToAccessUsersOrGroupDocuments = this.permissionDBManager .isAllowedToAccessUsersOrGroupDocuments(this.loginUser, grouping, groupingName, filter, session); if (!allowedToAccessUsersOrGroupDocuments) { param.setFilter(FilterEntity.JUST_POSTS); } else if (!present(filter)) { param.setFilter(FilterEntity.POSTS_WITH_DOCUMENTS); } // this is save because of RTTI-check of resourceType argument // which is of class T final List<Post<T>> publications = (List) this.publicationDBManager.getPosts(param, session); SystemTagsExtractor.handleHiddenSystemTags(publications, loginUser.getName()); return publications; } if (resourceType == Bookmark.class) { // check filters // can not add filter to BookmarkParam yet, but need to add // group before buildParam if (this.permissionDBManager.checkFilterPermissions(filter, this.loginUser)) { /* * FIXME: it is not safe, what is done here! * checkFilterPermissions only checks, if ANY filter is * applicable by loginUser. But here we assume * ADMIN_SPAM_POSTS has been checked! */ loginUser.addGroup(new Group(GroupID.PUBLIC_SPAM)); } final BookmarkParam param = LogicInterfaceHelper.buildParam(BookmarkParam.class, grouping, groupingName, tags, hash, order, start, end, search, filter, this.loginUser); final List<Post<T>> bookmarks = (List) this.bookmarkDBManager.getPosts(param, session); SystemTagsExtractor.handleHiddenSystemTags(bookmarks, loginUser.getName()); return bookmarks; } if (resourceType == GoldStandardPublication.class) { final BibTexParam param = LogicInterfaceHelper.buildParam(BibTexParam.class, grouping, groupingName, tags, hash, order, start, end, search, filter, this.loginUser); return (List) this.goldStandardPublicationDBManager.getPosts(param, session); } throw new UnsupportedResourceTypeException(); } catch (final QueryTimeoutException ex) { // if a query times out, we return an empty list return new ArrayList<Post<T>>(); } finally { session.close(); } } private boolean systemTagsAllowResourceType(final Collection<String> tags, final Class<? extends Resource> resourceType) { if (present(tags)) { for (final String tagName : tags) { final SearchSystemTag sysTag = SystemTagsUtil.createSearchSystemTag(tagName); if (present(sysTag)) { if (!sysTag.allowsResource(resourceType)) { return false; } } } } return true; } /* * (non-Javadoc) * * @see org.bibsonomy.model.logic.PostLogicInterface#getPostDetails(java.lang.String, java.lang.String) */ @Override public Post<? extends Resource> getPostDetails(final String resourceHash, final String userName) throws ResourceMovedException, ResourceNotFoundException { final DBSession session = this.openSession(); try { for (final CrudableContent<? extends Resource, ? extends GenericParam> manager : this.allDatabaseManagers .values()) { final Post<? extends Resource> post = manager.getPostDetails(this.loginUser.getName(), resourceHash, userName, UserUtils.getListOfGroupIDs(this.loginUser), session); /* * if a manager found a post, return it */ if (present(post)) { /* * XXX: can't be added to the postDatabaseManager; calls * getPostDetails with an emtpy list of visible groups */ final Resource resource = post.getResource(); final List<DiscussionItem> discussionSpace = this.discussionDatabaseManager .getDiscussionSpace(this.loginUser, resource.getInterHash(), session); resource.setDiscussionItems(discussionSpace); return post; } /* * check next manager */ } } finally { session.close(); } return null; } /* * (non-Javadoc) * * @see org.bibsonomy.model.logic.LogicInterface#getGroups(int, int) */ @Override public List<Group> getGroups(final int start, final int end) { final DBSession session = this.openSession(); try { return this.groupDBManager.getAllGroups(start, end, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getGroupDetails(java.lang.String * ) */ @Override public Group getGroupDetails(final String groupName) { final DBSession session = this.openSession(); try { final Group myGroup = this.groupDBManager.getGroupByName(groupName, session); if (present(myGroup)) { myGroup.setTagSets(this.groupDBManager.getGroupTagSets(groupName, session)); } return myGroup; } finally { session.close(); } } /* * (non-Javadoc) * * @see org.bibsonomy.model.logic.LogicInterface#getTags(java.lang.Class, * org.bibsonomy.common.enums.GroupingEntity, java.lang.String, * java.lang.String, java.util.List, java.lang.String, * org.bibsonomy.model.enums.Order, int, int, java.lang.String, * org.bibsonomy.common.enums.TagSimilarity) */ @Override public List<Tag> getTags(final Class<? extends Resource> resourceType, final GroupingEntity grouping, final String groupingName, final String regex, final List<String> tags, final String hash, final Order order, final int start, final int end, final String search, final TagSimilarity relation) { if (GroupingEntity.ALL.equals(grouping)) { this.permissionDBManager.checkStartEnd(loginUser, start, end, "Tag"); } final DBSession session = this.openSession(); try { final TagParam param = LogicInterfaceHelper.buildParam(TagParam.class, grouping, groupingName, tags, hash, order, start, end, search, null, this.loginUser); param.setTagRelationType(relation); if (resourceType == BibTex.class || resourceType == Bookmark.class || resourceType == Resource.class) { // this is save because of RTTI-check of resourceType argument // which is of class T param.setRegex(regex); // need to switch from class to string to ensure legibility of // Tags.xml param.setContentTypeByClass(resourceType); return this.tagDBManager.getTags(param, session); } throw new UnsupportedResourceTypeException( "The requested resourcetype (" + resourceType.getClass().getName() + ") is not supported."); } catch (final QueryTimeoutException ex) { // if a query times out, we return an empty list return new ArrayList<Tag>(); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getTagDetails(java.lang.String) */ @Override public Tag getTagDetails(final String tagName) { final DBSession session = openSession(); try { final TagParam param = LogicInterfaceHelper.buildParam(TagParam.class, null, this.loginUser.getName(), Arrays.asList(tagName), null, null, 0, 1, null, null, this.loginUser); return this.tagDBManager.getTagDetails(param, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#deleteUser(java.lang.String) */ @Override public void deleteUser(final String userName) { // TODO: take care of toLowerCase()! this.ensureLoggedIn(); /* * only an admin or the user himself may delete the account */ this.permissionDBManager.ensureIsAdminOrSelf(loginUser, userName); final DBSession session = openSession(); try { userDBManager.deleteUser(userName, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#deleteGroup(java.lang.String) */ @Override public void deleteGroup(final String groupName) { throw new UnsupportedOperationException("not yet available"); // final DBSession session = openSession(); // try { // groupDBManager.deleteGroup(groupName, session); // } finally { // session.close(); // } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#removeUserFromGroup(java.lang * .String, java.lang.String) */ @Override public void deleteUserFromGroup(final String groupName, final String userName) { // TODO: take care of toLowerCase()! // FIXME: IMPORTANT: not everybody may do this! // better do nothing than anything horribly wrong: throw new UnsupportedOperationException("not yet available"); // final DBSession session = openSession(); // try { // groupDBManager.removeUserFromGroup(groupName, userName, session); // } finally { // session.close(); // } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.PostLogicInterface#deletePosts(java.lang.String * , java.util.List) */ @Override public void deletePosts(final String userName, final List<String> resourceHashes) { /* * check permissions */ this.ensureLoggedIn(); this.permissionDBManager.ensureWriteAccess(this.loginUser, userName); /* * to store hashes of missing resources */ final List<String> missingResources = new LinkedList<String>(); final DBSession session = openSession(); try { final String lowerCaseUserName = userName.toLowerCase(); for (final String resourceHash : resourceHashes) { /* * delete one resource */ boolean resourceFound = false; // TODO would be nice to know about the resourcetype or the // instance behind this resourceHash for (final CrudableContent<? extends Resource, ? extends GenericParam> man : this.allDatabaseManagers .values()) { if (man.deletePost(lowerCaseUserName, resourceHash, session)) { resourceFound = true; break; } } /* * remember missing resources */ if (!resourceFound) { missingResources.add(resourceHash); } } } finally { session.close(); } /* * throw exception for missing resources */ if (missingResources.size() > 0) { throw new IllegalStateException("The resource(s) with ID(s) " + missingResources + " do(es) not exist and could hence not be deleted."); } } /** * Check for each group actually exist and if the * posting user is allowed to post. If yes, insert the correct group ID into * the given post's groups. * * @param groups the groups to validate */ protected void validateGroups(final User user, final Set<Group> groups, final DBSession session) { /* * First check for "public" and "private". Those two groups are special, * they can't be assigned with another group. */ if (GroupUtils.containsExclusiveGroup(groups)) { if (groups.size() > 1) { /* * Those two groups are exclusive - they can not appear together * or with any other group. */ throw new ValidationException( "Group 'public' (or 'private') can not be combined with other groups."); } /* * only one group and it is "public" or "private" -> set group id * and return post */ final Group group = groups.iterator().next(); if (group.equals(GroupUtils.getPrivateGroup())) { group.setGroupId(GroupUtils.getPrivateGroup().getGroupId()); } else { group.setGroupId(GroupUtils.getPublicGroup().getGroupId()); } } else { /* * only non-special groups remain (including "friends") - check * those */ /* * retrieve the user's groups */ final Set<Integer> groupIds = new HashSet<Integer>( this.groupDBManager.getGroupIdsForUser(user.getName(), session)); /* * add "friends" group */ groupIds.add(GroupID.FRIENDS.getId()); /* * check that there are only groups the user is allowed to post to. */ for (final Group group : groups) { final Group testGroup = this.groupDBManager.getGroupByName(group.getName().toLowerCase(), session); if (testGroup == null) { // group does not exist throw new ValidationException("Group " + group.getName() + " does not exist"); } if (!groupIds.contains(testGroup.getGroupId())) { // the posting user is not a member of this group throw new ValidationException( "User " + user.getName() + " is not a member of group " + group.getName()); } group.setGroupId(testGroup.getGroupId()); } } // no group specified -> make it public if (groups.size() == 0) { groups.add(GroupUtils.getPublicGroup()); } } /** * Helper method to retrieve an appropriate database manager * * @param <T> * extends Resource - the resource type * @param post * - a post of type T * @return an appropriate database manager */ @SuppressWarnings({ "rawtypes", "unchecked" }) private <T extends Resource> CrudableContent<T, GenericParam> getFittingDatabaseManager(final Post<T> post) { final Class<?> resourceClass = post.getResource().getClass(); CrudableContent<? extends Resource, ? extends GenericParam> man = this.allDatabaseManagers .get(resourceClass); if (man == null) { for (final Map.Entry<Class<? extends Resource>, CrudableContent<? extends Resource, ? extends GenericParam>> entry : this.allDatabaseManagers .entrySet()) { if (entry.getKey().isAssignableFrom(resourceClass)) { man = entry.getValue(); break; } } if (man == null) { throw new UnsupportedResourceTypeException(); } } return ((CrudableContent) man); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#addUserToGroup(java.lang.String, * java.lang.String) */ @Override public void addUserToGroup(final String groupName, final String userName) { // TODO: take care of toLowerCase()! throw new UnsupportedOperationException("not yet available"); // final DBSession session = openSession(); // try { // groupDBManager.addUserToGroup(groupName, userName, session); // } finally { // session.close(); // } } /** * helper method to check if a user is currently logged in */ private void ensureLoggedIn() { if (this.loginUser.getName() == null) { throw new AccessDeniedException("Please log in!"); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#createGroup(org.bibsonomy.model * .Group) */ @Override public String createGroup(final Group group) { this.ensureLoggedIn(); /* * check permissions */ this.permissionDBManager.ensureAdminAccess(loginUser); final DBSession session = this.openSession(); try { this.groupDBManager.createGroup(group, session); return group.getName(); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#updateGroup(org.bibsonomy.model * .Group) */ @Override public String updateGroup(final Group group, final GroupUpdateOperation operation) { this.ensureLoggedIn(); final String groupName = group.getName(); if (!(present(groupName) && present(group.getGroupId()) && present(group.getPrivlevel()) && present(group.isSharedDocuments()))) { throw new ValidationException("The given group is not valid."); } final DBSession session = this.openSession(); try { switch (operation) { case UPDATE_ALL: // this.groupDBManager.updateGroupSettings(group, session); //handle users throw new UnsupportedOperationException( "The method " + GroupUpdateOperation.UPDATE_ALL + " is not yet implemented."); case UPDATE_SETTINGS: this.groupDBManager.updateGroupSettings(group, session); break; case ADD_NEW_USER: throw new UnsupportedOperationException( "The method " + GroupUpdateOperation.ADD_NEW_USER + " is not yet implemented."); default: throw new UnsupportedOperationException("The given method is not yet implemented."); } } finally { session.close(); } return groupName; } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.PostLogicInterface#createPosts(java.util.List) */ @Override public List<String> createPosts(final List<Post<?>> posts) { // TODO: Which of these checks should result in a DatabaseException, this.ensureLoggedIn(); /* * check permissions */ for (final Post<?> post : posts) { PostUtils.populatePostWithUser(post, this.loginUser); PostUtils.populatePostWithDate(post, this.loginUser); this.permissionDBManager.ensureWriteAccess(post, this.loginUser); } /* * insert posts TODO: more efficient implementation (transactions, * deadlock handling, asynchronous, etc.) */ final List<String> hashes = new LinkedList<String>(); /* * open session to store all the posts */ final DBSession session = openSession(); final DatabaseException collectedException = new DatabaseException(); try { for (final Post<?> post : posts) { try { hashes.add(this.createPost(post, session)); } catch (final DatabaseException dbex) { collectedException.addErrors(dbex); } catch (final Exception ex) { // some exception other than those covered in the DatabaseException was thrown collectedException.addToErrorMessages(post.getResource().getIntraHash(), new UnspecifiedErrorMessage(ex)); } } } finally { session.close(); } if (collectedException.hasErrorMessages()) { throw collectedException; } return hashes; } /** * Adds a post in the database. */ private <T extends Resource> String createPost(final Post<T> post, final DBSession session) { final CrudableContent<T, GenericParam> manager = this.getFittingDatabaseManager(post); post.getResource().recalculateHashes(); /* *check and set post visibility for synchronization */ if (Role.SYNC.equals(this.loginUser.getRole())) { validateGroupsForSynchronization(post); } this.validateGroups(post.getUser(), post.getGroups(), session); /* * change group IDs to spam group IDs */ PostUtils.setGroupIds(post, this.loginUser); manager.createPost(post, session); // if we don't get an exception here, we assume the resource has // been successfully created return post.getResource().getIntraHash(); } /** * The given posts are updated. If the operation is {@link PostUpdateOperation#UPDATE_TAGS}, * the posts must only contain the * <ul> * <li>date, </li> * <li>tags,</li> * <li>intraHash,</li> * <li>and optionally a username. * </ul> * * @see * org.bibsonomy.model.logic.PostLogicInterface#updatePosts(java.util.List, org.bibsonomy.common.enums.PostUpdateOperation) */ @Override public List<String> updatePosts(final List<Post<?>> posts, final PostUpdateOperation operation) { // TODO: Which of these checks should result in a DatabaseException, // which do we want to handle otherwise (=status quo) // TODO: not everybody can update gold standard publication posts this.ensureLoggedIn(); /* * check permissions */ for (final Post<?> post : posts) { PostUtils.populatePostWithUser(post, this.loginUser); PostUtils.populatePostWithDate(post, this.loginUser); this.permissionDBManager.ensureWriteAccess(post, this.loginUser); } final List<String> hashes = new LinkedList<String>(); /* * open session */ final DBSession session = openSession(); final DatabaseException collectedException = new DatabaseException(); try { for (final Post<?> post : posts) { try { hashes.add(this.updatePost(post, operation, session)); } catch (final DatabaseException dbex) { collectedException.addErrors(dbex); } catch (final Exception ex) { // some exception other than those covered in the DatabaseException was thrown collectedException.addToErrorMessages(post.getResource().getIntraHash(), new UnspecifiedErrorMessage(ex)); } } } finally { session.close(); } if (collectedException.hasErrorMessages()) { throw collectedException; } return hashes; } /** * Updates a post in the database. */ private <T extends Resource> String updatePost(final Post<T> post, final PostUpdateOperation operation, final DBSession session) { final CrudableContent<T, GenericParam> manager = getFittingDatabaseManager(post); final String oldIntraHash = post.getResource().getIntraHash(); if (Role.SYNC.equals(loginUser.getRole())) { validateGroupsForSynchronization(post); } this.validateGroups(post.getUser(), post.getGroups(), session); /* * change group IDs to spam group IDs */ PostUtils.setGroupIds(post, this.loginUser); /* * XXX: this is a "hack" and will be replaced soon * If the operation is UPDATE_URLS then create/delete the url right here and * return the intra hash. */ if (PostUpdateOperation.UPDATE_URLS_ADD.equals(operation)) { log.debug("Adding URL in updatePost()/DBLogic.java"); final BibTex resource = (BibTex) post.getResource(); final BibTexExtra resourceExtra = resource.getExtraUrls().get(0); resourceExtra.setDate(new Date()); bibTexExtraDBManager.createURL(post.getResource().getIntraHash(), this.loginUser.getName(), resourceExtra.getUrl().toExternalForm(), resourceExtra.getText(), session); return post.getResource().getIntraHash(); } else if (PostUpdateOperation.UPDATE_URLS_DELETE.equals(operation)) { log.debug("Deleting URL in updatePost()/DBLogic.java"); final BibTex resource = (BibTex) post.getResource(); final BibTexExtra resourceExtra = resource.getExtraUrls().get(0); bibTexExtraDBManager.deleteURL(post.getResource().getIntraHash(), this.loginUser.getName(), resourceExtra.getUrl().toExternalForm(), session); return post.getResource().getIntraHash(); } /* * update post */ manager.updatePost(post, oldIntraHash, operation, session, loginUser); // if we don't get an exception here, we assume the resource has // been successfully updated return post.getResource().getIntraHash(); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#updateTags(org.bibsonomy.model * .User, java.util.List, java.util.List) <p>TODO: possible options which * one might want to add:</p> <ul> <li>ignore case</li> </ul> */ @Override public int updateTags(final User user, final List<Tag> tagsToReplace, final List<Tag> replacementTags, final boolean updateRelations) { this.ensureLoggedIn(); this.permissionDBManager.ensureWriteAccess(loginUser, user.getName()); /* * */ final DBSession session = this.openSession(); try { if (updateRelations) { if (tagsToReplace.size() != 1 || replacementTags.size() != 1) { throw new ValidationException( "tag relations can only be updated, when exactly one tag is exchanged by exactly one other tag."); } this.tagRelationsDBManager.updateTagRelations(user, tagsToReplace.get(0), replacementTags.get(0), session); } /* * finally delegate to tagDBManager */ return this.tagDBManager.updateTags(user, tagsToReplace, replacementTags, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#createUser(org.bibsonomy.model * .User) */ @Override public String createUser(final User user) { /* * We ensure, that the user is logged in and has admin privileges. This * seems to be a contradiction, because if a user wants to register, he * is not logged in. * * The current solution to this paradox is, that registration is done * using an instance of the DBLogic which contains a user with role * "admin". */ this.ensureLoggedIn(); this.permissionDBManager.ensureAdminAccess(loginUser); return this.storeUser(user, false); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#updateUser(org.bibsonomy.model * .User) */ @Override public String updateUser(final User user, final UserUpdateOperation operation) { /* * only logged in users can update user settings. */ if (!UserUpdateOperation.ACTIVATE.equals(operation)) { this.ensureLoggedIn(); /* * only admins can change settings of /other/ users */ this.permissionDBManager.ensureIsAdminOrSelf(loginUser, user.getName()); } final DBSession session = openSession(); try { switch (operation) { case UPDATE_PASSWORD: return this.userDBManager.updatePasswordForUser(user, session); case UPDATE_SETTINGS: return this.userDBManager.updateUserSettingsForUser(user, session); case UPDATE_API: this.userDBManager.updateApiKeyForUser(user.getName(), session); break; case UPDATE_CORE: return this.userDBManager.updateUserProfile(user, session); case ACTIVATE: return this.userDBManager.activateUser(user, session); case UPDATE_ALL: /* * update only (!) spammer settings * * FIXME: use a separate operation for that! */ if (user.getPrediction() != null || user.getSpammer() != null) { /* * only admins are allowed to change spammer settings */ log.debug("Start update this framework"); this.permissionDBManager.ensureAdminAccess(loginUser); /* * open session and update spammer settings */ final String mode = this.adminDBManager.getClassifierSettings(ClassifierSettings.TESTING, session); log.debug("User prediction: " + user.getPrediction()); return this.adminDBManager.flagSpammer(user, this.getAuthenticatedUser().getName(), mode, session); } return this.storeUser(user, true); } } finally { session.close(); } return null; } /** * TODO: extract the method to create and update user * * Adds/updates a user in the database. */ private String storeUser(final User user, final boolean update) { final DBSession session = openSession(); try { final User existingUser = userDBManager.getUserDetails(user.getName(), session); final List<User> pendingUserList = userDBManager.getPendingUserByUsername(user.getName(), 0, Integer.MAX_VALUE, session); if (update) { /* * update the user */ if (!present(existingUser.getName())) { /* * error: user name does not exist */ throw new ValidationException("user " + user.getName() + " does not exist"); } return this.userDBManager.updateUser(user, session); } /* * create a new user */ if (present(existingUser.getName()) || pendingUserList.size() > 0) { /* * error: user name already exists */ throw new ValidationException("user " + user.getName() + " already exists"); } return this.userDBManager.createUser(user, session); } finally { /* * TODO: check, if rollback is handled correctly! */ session.close(); } } /* * (non-Javadoc) * * @see org.bibsonomy.model.logic.LogicInterface#getAuthenticatedUser() */ @Override public User getAuthenticatedUser() { return this.loginUser; } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getAuthors(org.bibsonomy.common * .enums.GroupingEntity, java.lang.String, java.util.List, * java.lang.String, org.bibsonomy.model.enums.Order, * org.bibsonomy.common.enums.FilterEntity, int, int, java.lang.String) */ @Override public List<Author> getAuthors(final GroupingEntity grouping, final String groupingName, final List<String> tags, final String hash, final Order order, final FilterEntity filter, final int start, final int end, final String search) { /* * FIXME: implement a chain or something similar */ final DBSession session = openSession(); try { if (GroupingEntity.ALL.equals(grouping)) { return this.authorDBManager.getAuthors(session); } throw new UnsupportedOperationException("Currently only ALL authors can be listed."); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#addDocument(org.bibsonomy.model * .Document, java.lang.String) */ @Override public String createDocument(final Document document, final String resourceHash) { this.ensureLoggedIn(); final String userName = document.getUserName(); /* * users can only modify their own documents */ this.permissionDBManager.ensureWriteAccess(this.loginUser, userName); final DBSession session = openSession(); try { if (resourceHash != null) { /* * document shall be attached to a post */ Post<BibTex> post = null; try { post = publicationDBManager.getPostDetails(this.loginUser.getName(), resourceHash, userName, UserUtils.getListOfGroupIDs(this.loginUser), session); } catch (final ResourceMovedException ex) { // ignore } catch (final ResourceNotFoundException ex) { // ignore } if (present(post)) { /* * post really exists! */ final boolean existingDoc = this.docDBManager.checkForExistingDocuments(userName, resourceHash, document.getFileName(), session); if (existingDoc) { /* * the post has already a file with that name attached * ... */ this.docDBManager.updateDocument(post.getContentId(), document.getFileHash(), document.getFileName(), document.getMd5hash(), session); } else { // add this.docDBManager.addDocument(userName, post.getContentId(), document.getFileHash(), document.getFileName(), document.getMd5hash(), session); } } else { throw new ValidationException("Could not find a post with hash '" + resourceHash + "'."); } } else { // checks whether a layout definition is already uploaded // if not the new one will be stored in the database if (this.docDBManager.getDocument(userName, document.getFileHash(), session) == null) { this.docDBManager.addDocument(userName, DocumentDatabaseManager.DEFAULT_CONTENT_ID, document.getFileHash(), document.getFileName(), document.getMd5hash(), session); } } } finally { session.close(); } log.info("created new file " + document.getFileName() + " for user " + userName); return document.getFileHash(); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getDocument(java.lang.String, * java.lang.String) */ @Override public Document getDocument(final String userName, final String fileHash) { this.ensureLoggedIn(); final String lowerCaseUserName = userName.toLowerCase(); this.permissionDBManager.ensureWriteAccess(this.loginUser, lowerCaseUserName); final DBSession session = openSession(); try { return docDBManager.getDocument(lowerCaseUserName, fileHash, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getDocument(java.lang.String, * java.lang.String, java.lang.String) */ @Override public Document getDocument(final String userName, final String resourceHash, final String fileName) { this.ensureLoggedIn(); final String lowerCaseUserName = userName.toLowerCase(); final DBSession session = openSession(); try { if (present(resourceHash)) { /* * we just forward this task to getPostDetails from the * BibTeXDatabaseManager and extract the documents. */ Post<BibTex> post = null; try { post = this.publicationDBManager.getPostDetails(this.loginUser.getName(), resourceHash, lowerCaseUserName, UserUtils.getListOfGroupIDs(this.loginUser), session); } catch (final ResourceMovedException ex) { // ignore } catch (final ResourceNotFoundException ex) { // ignore } if (post != null && post.getResource().getDocuments() != null) { /* * post found and post contains documents (bibtexdbmanager * checks, if user might access documents and only then * inserts them) */ for (final Document document : post.getResource().getDocuments()) { if (document.getFileName().equals(fileName)) { return document; } } } } else { /* * users can only access their own documents */ this.permissionDBManager.ensureWriteAccess(this.loginUser, lowerCaseUserName); /* * TODO: implement access to non post-connected documents */ } } finally { session.close(); } return null; } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#deleteDocument(java.lang.String, * java.lang.String, java.lang.String) */ @Override public void deleteDocument(final Document document, final String resourceHash) { this.ensureLoggedIn(); final String userName = document.getUserName(); /* * users can only modify their own documents */ this.permissionDBManager.ensureWriteAccess(this.loginUser, userName); final DBSession session = openSession(); try { if (resourceHash != null) { /* * the document belongs to a post --> check if the user owns the * post */ Post<BibTex> post = null; try { post = publicationDBManager.getPostDetails(this.loginUser.getName(), resourceHash, userName, UserUtils.getListOfGroupIDs(this.loginUser), session); } catch (final ResourceMovedException ex) { //ignore } catch (final ResourceNotFoundException ex) { // ignore } if (post != null) { /* * the given resource hash belongs to a post of the user -> * delete the corresponding document */ if (this.docDBManager.checkForExistingDocuments(userName, resourceHash, document.getFileName(), session)) { this.docDBManager.deleteDocument(post.getContentId(), userName, document.getFileName(), session); } } else { throw new ValidationException("Could not find a post with hash '" + resourceHash + "'."); } } else { /* * the document does not belong to a post */ this.docDBManager.deleteDocumentWithNoPost(DocumentDatabaseManager.DEFAULT_CONTENT_ID, userName, document.getFileHash(), session); } } finally { session.close(); } log.debug("deleted document " + document.getFileName() + " from user " + userName); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#addInetAddressStatus(java.net * .InetAddress, org.bibsonomy.common.enums.InetAddressStatus) */ @Override public void createInetAddressStatus(final InetAddress address, final InetAddressStatus status) { this.ensureLoggedIn(); // only admins are allowed to change the status of an address this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { this.adminDBManager.addInetAddressStatus(address, status, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#deleteInetAdressStatus(java. * net.InetAddress) */ @Override public void deleteInetAdressStatus(final InetAddress address) { this.ensureLoggedIn(); // only admins are allowed to change the status of an address this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { this.adminDBManager.deleteInetAdressStatus(address, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getInetAddressStatus(java.net * .InetAddress) */ @Override public InetAddressStatus getInetAddressStatus(final InetAddress address) { // everybody is allowed to ask for the status of an address /* * TODO: is this really OK? At least it is neccessary, because otherwise * the RegistrationHandler can not check the status of an address. */ // this.ensureLoggedIn(); // this.permissionDBManager.ensureAdminAccess(loginUser); final DBSession session = openSession(); try { return this.adminDBManager.getInetAddressStatus(address, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.PostLogicInterface#getPostStatistics(java.lang * .Class, org.bibsonomy.common.enums.GroupingEntity, java.lang.String, * java.util.List, java.lang.String, org.bibsonomy.model.enums.Order, * org.bibsonomy.common.enums.FilterEntity, int, int, java.lang.String, * org.bibsonomy.common.enums.StatisticsConstraint) */ @Override public int getPostStatistics(final Class<? extends Resource> resourceType, final GroupingEntity grouping, final String groupingName, final List<String> tags, final String hash, final Order order, final FilterEntity filter, final int start, final int end, final String search, final StatisticsConstraint constraint) { final DBSession session = openSession(); try { if (this.permissionDBManager.checkFilterPermissions(filter, this.loginUser)) { loginUser.addGroup(new Group(GroupID.PUBLIC_SPAM)); } final StatisticsParam param = LogicInterfaceHelper.buildParam(StatisticsParam.class, grouping, groupingName, tags, hash, order, start, end, search, filter, this.loginUser); if (resourceType == GoldStandardPublication.class || resourceType == BibTex.class || resourceType == Bookmark.class || resourceType == Resource.class) { param.setContentTypeByClass(resourceType); return this.statisticsDBManager.getPostStatistics(param, session); } throw new UnsupportedResourceTypeException( "The requested resourcetype (" + resourceType.getClass().getName() + ") is not supported."); } catch (final QueryTimeoutException ex) { // if a query times out, we return 0 (cause we also retun empty list when a query timeout exception is thrown) return 0; } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getConcepts(java.lang.Class, * org.bibsonomy.common.enums.GroupingEntity, java.lang.String, * java.lang.String, java.util.List, * org.bibsonomy.common.enums.ConceptStatus, int, int) */ @Override public List<Tag> getConcepts(final Class<? extends Resource> resourceType, final GroupingEntity grouping, final String groupingName, final String regex, final List<String> tags, final ConceptStatus status, final int start, final int end) { final DBSession session = openSession(); try { final TagRelationParam param = LogicInterfaceHelper.buildParam(TagRelationParam.class, grouping, groupingName, tags, null, null, start, end, null, null, this.loginUser); param.setConceptStatus(status); return this.tagRelationsDBManager.getConcepts(param, session); } finally { session.close(); } } /** * @return a concept, i.e. a tag with its assigned subtags * * in both queries getConceptForUser and getGlobalConceptByName * the case of parameter conceptName is ignored * * @see * org.bibsonomy.model.logic.LogicInterface#getConceptDetails(java.lang. * String, org.bibsonomy.common.enums.GroupingEntity, java.lang.String) */ @Override public Tag getConceptDetails(final String conceptName, final GroupingEntity grouping, final String groupingName) { final DBSession session = openSession(); try { if (GroupingEntity.USER.equals(grouping) || GroupingEntity.GROUP.equals(grouping) && present(groupingName)) { return this.tagRelationsDBManager.getConceptForUser(conceptName, groupingName, session); } else if (GroupingEntity.ALL.equals(grouping)) { return this.tagRelationsDBManager.getGlobalConceptByName(conceptName, session); } throw new RuntimeException("Can't handle request"); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#createConcept(org.bibsonomy. * model.Tag, org.bibsonomy.common.enums.GroupingEntity, java.lang.String) */ @Override public String createConcept(final Tag concept, final GroupingEntity grouping, final String groupingName) { if (GroupingEntity.USER.equals(grouping)) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, groupingName); return this.storeConcept(concept, grouping, groupingName, false); } throw new UnsupportedOperationException("Currently, tag relations can only be created for users."); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#deleteConcept(java.lang.String, * org.bibsonomy.common.enums.GroupingEntity, java.lang.String) */ @Override public void deleteConcept(final String concept, final GroupingEntity grouping, final String groupingName) { if (GroupingEntity.USER.equals(grouping)) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, groupingName); final DBSession session = openSession(); try { this.tagRelationsDBManager.deleteConcept(concept, groupingName, session); } finally { session.close(); } return; } throw new UnsupportedOperationException("Currently, tag relations can only be deleted for users."); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#deleteRelation(java.lang.String, * java.lang.String, org.bibsonomy.common.enums.GroupingEntity, * java.lang.String) */ @Override public void deleteRelation(final String upper, final String lower, final GroupingEntity grouping, final String groupingName) { if (GroupingEntity.USER.equals(grouping)) { this.permissionDBManager.ensureIsAdminOrSelf(loginUser, groupingName); final DBSession session = openSession(); try { this.tagRelationsDBManager.deleteRelation(upper, lower, groupingName, session); return; } finally { session.close(); } } throw new UnsupportedOperationException("Currently, tag relations can only be created for users."); } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#updateConcept(org.bibsonomy. * model.Tag, org.bibsonomy.common.enums.GroupingEntity, java.lang.String) */ @Override public String updateConcept(final Tag concept, final GroupingEntity grouping, final String groupingName, final ConceptUpdateOperation operation) { if (!GroupingEntity.USER.equals(grouping)) { throw new UnsupportedOperationException("Currently only user's can have concepts."); } this.permissionDBManager.ensureIsAdminOrSelf(loginUser, groupingName); final DBSession session = openSession(); // now switch the operation and call the right method in the taglRelationsDBManager or DBLogic try { switch (operation) { case UPDATE: return this.storeConcept(concept, grouping, groupingName, true); case PICK: this.tagRelationsDBManager.pickConcept(concept, groupingName, session); break; case UNPICK: this.tagRelationsDBManager.unpickConcept(concept, groupingName, session); break; case UNPICK_ALL: this.tagRelationsDBManager.unpickAllConcepts(groupingName, session); return null; case PICK_ALL: this.tagRelationsDBManager.pickAllConcepts(groupingName, session); return null; } return concept.getName(); } finally { session.close(); } } /** * Helper metod to store a concept * * @param concept * @param grouping * @param groupingName * @param update * @return */ private String storeConcept(final Tag concept, final GroupingEntity grouping, final String groupingName, final boolean update) { final DBSession session = openSession(); if (update) { this.tagRelationsDBManager.insertRelations(concept, groupingName, session); } else { this.deleteConcept(concept.getName(), grouping, groupingName); this.tagRelationsDBManager.insertRelations(concept, groupingName, session); } return concept.getName(); } /* * (non-Javadoc) * * @see org.bibsonomy.model.logic.LogicInterface#getUsers(java.lang.Class, * org.bibsonomy.common.enums.GroupingEntity, java.lang.String, * java.util.List, java.lang.String, org.bibsonomy.model.enums.Order, * org.bibsonomy.common.enums.UserRelation, java.lang.String, int, int) */ @Override public List<User> getUsers(final Class<? extends Resource> resourceType, final GroupingEntity grouping, final String groupingName, final List<String> tags, final String hash, final Order order, final UserRelation relation, final String search, final int start, final int end) { // assemble param object final UserParam param = LogicInterfaceHelper.buildParam(UserParam.class, grouping, groupingName, tags, hash, order, start, end, search, null, loginUser); param.setUserRelation(relation); // check start/end values if (GroupingEntity.ALL.equals(grouping)) { this.permissionDBManager.checkStartEnd(loginUser, start, end, "User"); } final DBSession session = openSession(); try { // start chain return this.userDBManager.getUsers(param, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getClassifiedUsers(org.bibsonomy * .common.enums.Classifier, org.bibsonomy.common.enums.SpamStatus, int) */ @Override public List<User> getClassifiedUsers(final Classifier classifier, final SpamStatus status, final int limit) { this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { return this.adminDBManager.getClassifiedUsers(classifier, status, limit, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getClassifierSettings(org.bibsonomy * .common.enums.ClassifierSettings) */ @Override public String getClassifierSettings(final ClassifierSettings key) { this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { return this.adminDBManager.getClassifierSettings(key, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#updateClassifierSettings(org * .bibsonomy.common.enums.ClassifierSettings, java.lang.String) */ @Override public void updateClassifierSettings(final ClassifierSettings key, final String value) { this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { this.adminDBManager.updateClassifierSettings(key, value, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getClassifiedUserCount(org.bibsonomy * .common.enums.Classifier, org.bibsonomy.common.enums.SpamStatus, int) */ @Override public int getClassifiedUserCount(final Classifier classifier, final SpamStatus status, final int interval) { this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { return this.adminDBManager.getClassifiedUserCount(classifier, status, interval, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getClassifierHistory(java.lang * .String) */ @Override public List<User> getClassifierHistory(final String userName) { this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { return this.adminDBManager.getClassifierHistory(userName, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getClassifierComparison(int) */ @Override public List<User> getClassifierComparison(final int interval, final int limit) { this.permissionDBManager.ensureAdminAccess(this.loginUser); final DBSession session = openSession(); try { return this.adminDBManager.getClassifierComparison(interval, limit, session); } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getOpenIDUser(java.lang.String) */ @Override public String getOpenIDUser(final String openID) { final DBSession session = openSession(); try { final String username = this.userDBManager.getOpenIDUser(openID, session); return username; } finally { session.close(); } } /* * (non-Javadoc) * * @see * org.bibsonomy.model.logic.LogicInterface#getTagStatistics(java.lang.Class * , org.bibsonomy.common.enums.GroupingEntity, java.lang.String, * java.lang.String, java.util.List, * org.bibsonomy.common.enums.ConceptStatus, int, int) */ @Override public int getTagStatistics(final Class<? extends Resource> resourceType, final GroupingEntity grouping, final String groupingName, final String regex, final List<String> tags, final ConceptStatus status, final int start, final int end) { Integer result; final DBSession session = openSession(); try { final StatisticsParam param = LogicInterfaceHelper.buildParam(StatisticsParam.class, grouping, groupingName, tags, null, null, start, end, null, null, this.loginUser); result = this.statisticsDBManager.getTagStatistics(param, session); } finally { session.close(); } return result; } /* * We create a UserRelation of the form (sourceUser, targetUser)\in relation * This Method only works for the FOLLOWER_OF and the OF_FRIEND relation * Other relation will result in an UnsupportedRelationException * * TODO: the "tag" parameter is currently ignored by this function. As soon * as tagged relationships are needed, please implement the handling of * the "tag" parameter from here on (mainly in the UserDBManager) * * @see org.bibsonomy.model.logic.LogicInterface#insertUserRelationship() */ @Override public void createUserRelationship(final String sourceUser, final String targetUser, final UserRelation relation, final String tag) { this.ensureLoggedIn(); /* * relationships can only be created by the logged-in user or admins */ this.permissionDBManager.ensureIsAdminOrSelf(loginUser, sourceUser); /* * check if relationship may be created (e.g. some special users * like 'dblp' are disallowed) */ final DBSession session = openSession(); this.permissionDBManager.checkUserRelationship(loginUser, this.userDBManager.getUserDetails(targetUser, session), relation, tag); /* * finally try to create relationship */ try { this.userDBManager.createUserRelation(sourceUser, targetUser, relation, tag, session); } finally { session.close(); } } /* * * TODO: the "tag" parameter is currently ignored by this function. As soon * as tagged relationships are needed, please implement the handling of * the "tag" parameter from here on (mainly in the UserDBManager) * * (non-Javadoc) * @see org.bibsonomy.model.logic.LogicInterface#getUserRelationship(java.lang.String, org.bibsonomy.common.enums.UserRelation) */ @Override public List<User> getUserRelationship(final String sourceUser, final UserRelation relation, final String tag) { this.ensureLoggedIn(); // ask Robert about this method // this.permissionDBManager.checkUserRelationship(sourceUser, targetUser, relation); this.permissionDBManager.ensureIsAdminOrSelf(loginUser, sourceUser); final DBSession session = openSession(); try { // get all users that are in relation with sourceUser return this.userDBManager.getUserRelation(sourceUser, relation, tag, session); } finally { // unsupported Relations will cause an UnsupportedRelationException session.close(); } } /* * We delete a UserRelation of the form (sourceUser, targetUser)\in relation * This Method only works for the FOLLOWER_OF and the OF_FRIEND relation * Other relation will result in an UnsupportedRelationException FIXME: use * Strings (usernames) instead of users * * TODO: the "tag" parameter is currently ignored by this function. As soon * as tagged relationships are needed, please implement the handling of * the "tag" parameter from here on (mainly in the UserDBManager) * * @see org.bibsonomy.model.logic.LogicInterface#deleteUserRelationship() */ @Override public void deleteUserRelationship(final String sourceUser, final String targetUser, final UserRelation relation, final String tag) { this.ensureLoggedIn(); // ask Robert about this method // this.permissionDBManager.checkUserRelationship(sourceUser, targetUser, relation); this.permissionDBManager.ensureIsAdminOrSelf(loginUser, sourceUser); final DBSession session = openSession(); try { this.userDBManager.deleteUserRelation(sourceUser, targetUser, relation, tag, session); } finally { // unsupported Relations will cause an UnsupportedRelationException session.close(); } } /* * (non-Javadoc) * * @see org.bibsonomy.model.logic.LogicInterface#createBasketItems() */ @Override public int createBasketItems(final List<Post<? extends Resource>> posts) { this.ensureLoggedIn(); final DBSession session = openSession(); try { for (final Post<? extends Resource> post : posts) { if (post.getResource() instanceof Bookmark) { throw new UnsupportedResourceTypeException("Bookmarks can't be stored in the basket"); } /* * get the complete post from the database */ final String intraHash = post.getResource().getIntraHash(); final String postUserName = post.getUser().getName(); final Post<BibTex> copy = this.publicationDBManager.getPostDetails(this.loginUser.getName(), intraHash, postUserName, UserUtils.getListOfGroupIDs(this.loginUser), session); /* * post might be null, because a) it does not exist b) user may * not access it */ if (copy == null) { /* * TODO: exception handling?! */ throw new ValidationException( "Post with hash " + intraHash + " of user " + postUserName + " not found!"); } /* * insert the post from the user's basket */ this.basketDBManager.createItem(this.loginUser.getName(), copy.getContentId(), session); } // get actual basket size return this.basketDBManager.getNumBasketEntries(this.loginUser.getName(), session); } catch (final Exception ex) { log.error(ex); } finally { session.close(); } return 0; } /* * (non-Javadoc) * * @see org.bibsonomy.model.logic.LogicInterface#deleteBasketItems() */ @Override public int deleteBasketItems(final List<Post<? extends Resource>> posts, final boolean clearBasket) { this.ensureLoggedIn(); final DBSession session = openSession(); try { // decide which delete function will be called if (clearBasket) { // clear all in basket this.basketDBManager.deleteAllItems(this.loginUser.getName(), session); } else { // delete specific post for (final Post<? extends Resource> post : posts) { if (post.getResource() instanceof Bookmark) { throw new UnsupportedResourceTypeException("Bookmarks can't be stored in the basket"); } /* * get the complete post from the database */ final Post<BibTex> copy = this.publicationDBManager.getPostDetails(this.loginUser.getName(), post.getResource().getIntraHash(), post.getUser().getName(), UserUtils.getListOfGroupIDs(this.loginUser), session); /* * post might be null, because a) it does not exist b) user * may not access it */ if (copy == null) { /* * FIXME: proper exception message! */ throw new ValidationException("You are not authorized to perform the requested operation"); } /* * delete the post from the user's basket */ this.basketDBManager.deleteItem(this.loginUser.getName(), copy.getContentId(), session); } } // get actual basketsize return this.basketDBManager.getNumBasketEntries(this.loginUser.getName(), session); } catch (final Exception ex) { log.error(ex); } finally { session.close(); } return 0; } /* * (non-Javadoc) * @see org.bibsonomy.model.logic.LogicInterface#deleteInboxMessages(java.util.List, boolean) */ @Override public int deleteInboxMessages(final List<Post<? extends Resource>> posts, final boolean clearInbox) { /* * check permissions */ this.ensureLoggedIn(); /* * delete one message from the inbox */ final DBSession session = openSession(); try { if (clearInbox) { this.inboxDBManager.deleteAllInboxMessages(loginUser.getName(), session); } else { for (final Post<? extends Resource> post : posts) { final String sender = post.getUser().getName(); final String receiver = loginUser.getName(); final String resourceHash = post.getResource().getIntraHash(); if (!present(receiver) || !present(resourceHash)) { /* * FIXME: proper exception message! */ throw new ValidationException("You are not authorized to perform the requested operation"); } this.inboxDBManager.deleteInboxMessage(sender, receiver, resourceHash, session); } } return this.inboxDBManager.getNumInboxMessages(loginUser.getName(), session); } finally { session.close(); } } /* * FIXME: implement this method as chain element of getUsers() * * @see org.bibsonomy.model.logic.LogicInterface#getUsernameByLdapUserId() */ @Override public String getUsernameByLdapUserId(final String userId) { final DBSession session = openSession(); try { return this.userDBManager.getUsernameByLdapUser(userId, session); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.logic.GoldStandardPostLogicInterface#createReferences(java.lang.String, java.util.Set) */ @Override public void createReferences(final String postHash, final Set<String> references) { this.permissionDBManager.ensureAdminAccess(loginUser); // only admins can create references final DBSession session = this.openSession(); try { this.goldStandardPublicationDBManager.addReferencesToPost(this.loginUser.getName(), postHash, references, session); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.logic.GoldStandardPostLogicInterface#deleteReferences(java.lang.String, java.util.Set) */ @Override public void deleteReferences(final String postHash, final Set<String> references) { this.permissionDBManager.ensureAdminAccess(loginUser); // only admins can delete references final DBSession session = this.openSession(); try { this.goldStandardPublicationDBManager.removeReferencesFromPost(this.loginUser.getName(), postHash, references, session); } finally { session.close(); } } @Override public void createWiki(final String userName, final Wiki wiki) { this.permissionDBManager.ensureIsAdminOrSelf(this.loginUser, userName); final DBSession session = openSession(); try { this.wikiDBManager.createWiki(userName, wiki, session); } finally { session.close(); } } @Override public void deleteWiki(final String userName) { throw new UnsupportedOperationException(); } /** * @param date - if <code>null</code>, the latest version of the wiki is * returned. Otherwise, the latest version before <code>date</code>. * * @see org.bibsonomy.model.logic.LogicInterface#getWiki(java.lang.String, java.util.Date) */ @Override public Wiki getWiki(final String userName, final Date date) { final DBSession session = openSession(); try { final User requUser = this.getUserDetails(userName); /* * We return an empty wiki for users who are not allowed to access * this wiki. */ if (!this.permissionDBManager.isAllowedToAccessUsersProfile(requUser, this.loginUser, session)) { return new Wiki(); } if (date == null) { return this.wikiDBManager.getActualWiki(userName, session); } return this.wikiDBManager.getPreviousWiki(userName, date, session); } finally { session.close(); } } @Override public List<Date> getWikiVersions(final String userName) { this.permissionDBManager.ensureIsAdminOrSelf(this.loginUser, userName); final DBSession session = openSession(); try { return this.wikiDBManager.getWikiVersions(userName, session); } finally { session.close(); } } @Override public void updateWiki(final String userName, final Wiki wiki) { this.permissionDBManager.ensureIsAdminOrSelf(this.loginUser, userName); final DBSession session = openSession(); try { final Wiki actual = this.wikiDBManager.getActualWiki(userName, session); /* * Check, if the wiki has changed (otherwise we don't update it). */ final String actualWikiText = actual.getWikiText(); if (present(actualWikiText) && !actualWikiText.equals(wiki.getWikiText())) { this.wikiDBManager.updateWiki(userName, wiki, session); this.wikiDBManager.logWiki(userName, actual, session); } } finally { session.close(); } } @Override public void createExtendedField(final Class<? extends Resource> resourceType, final String userName, final String intraHash, final String key, final String value) { final DBSession session = openSession(); try { if (BibTex.class == resourceType) { this.publicationDBManager.createExtendedField(userName, intraHash, key, value, session); } else { throw new UnsupportedResourceTypeException( "The requested resourcetype (" + resourceType.getClass().getName() + ") is not supported."); } } finally { session.close(); } } @Override public void deleteExtendedField(final Class<? extends Resource> resourceType, final String userName, final String intraHash, final String key, final String value) { final DBSession session = this.openSession(); try { if (BibTex.class == resourceType) { if (!present(key)) { this.publicationDBManager.deleteAllExtendedFieldsData(userName, intraHash, session); } else { if (!present(value)) { this.publicationDBManager.deleteExtendedFieldsByKey(userName, intraHash, key, session); } else { this.publicationDBManager.deleteExtendedFieldByKeyValue(userName, intraHash, key, value, session); } } } else { throw new UnsupportedResourceTypeException( "The requested resourcetype (" + resourceType.getClass().getName() + ") is not supported."); } } finally { session.close(); } } @Override public Map<String, List<String>> getExtendedFields(final Class<? extends Resource> resourceType, final String userName, final String intraHash, final String key) { final DBSession session = this.openSession(); try { if (BibTex.class == resourceType) { return this.publicationDBManager.getExtendedFields(userName, intraHash, key, session); } throw new UnsupportedResourceTypeException( "The requested resourcetype (" + resourceType.getClass().getName() + ") is not supported."); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.logic.ReviewLogicInterface#getReviews(java.lang.String) */ @Override public List<DiscussionItem> getDiscussionSpace(final String interHash) { final DBSession session = this.openSession(); try { return this.discussionDatabaseManager.getDiscussionSpace(this.loginUser, interHash, session); } finally { session.close(); } } /* * (non-Javadoc) * @see org.bibsonomy.model.logic.DiscussionLogicInterface#createDiscussionItem(java.lang.String, java.lang.String, org.bibsonomy.model.DiscussionItem) */ @Override public void createDiscussionItem(final String interHash, final String username, final DiscussionItem discussionItem) { this.permissionDBManager.ensureIsAdminOrSelf(this.loginUser, username); final DBSession session = this.openSession(); try { /* * first check if gold standard post exists */ @SuppressWarnings("unchecked") // should be a gold standard publication final Post<GoldStandardPublication> goldStandardPostinDB = (Post<GoldStandardPublication>) this .getPostDetails(interHash, ""); /* * if not create one * TODO: add a test */ if (!present(goldStandardPostinDB)) { log.debug("no gold standard publication found for interHash " + interHash + ". Creating new gold standard publication"); final String hash = HashID.INTER_HASH.getId() + interHash; // TODO: bookmarks are missing // final List<Post<Bookmark>> bookmarkPost = this.getPosts(Bookmark.class, GroupingEntity.USER, null, Collections.<String>emptyList(), hash, null, null, 0, 1, null); // FIXME: this list maybe also contains private posts of the logged in user! final List<Post<BibTex>> publicationPosts = this.getPosts(BibTex.class, GroupingEntity.ALL, null, Collections.<String>emptyList(), hash, null, null, 0, 1, null); if (present(publicationPosts)) { final Post<GoldStandardPublication> goldStandardPost = new Post<GoldStandardPublication>(); final GoldStandardPublication goldStandardPublication = new GoldStandardPublication(); ObjectUtils.copyPropertyValues(publicationPosts.get(0).getResource(), goldStandardPublication); /* * clear some private stuff */ goldStandardPublication.setPrivnote(""); goldStandardPost.setResource(goldStandardPublication); this.createPosts(Collections.<Post<?>>singletonList(goldStandardPost)); } else { // TODO: log? } } /* * create the discussion item */ final User commentUser = this.userDBManager.getUserDetails(username, session); discussionItem.setUser(commentUser); this.createDiscussionItem(interHash, discussionItem, session); } finally { session.close(); } } private void prepareComment(final User commentUser, final Set<Group> groups, final DBSession session) { this.validateGroups(commentUser, groups, session); // transfer to spammer group id's if neccessary GroupUtils.prepareGroups(groups, commentUser.isSpammer()); } private <D extends DiscussionItem> void createDiscussionItem(final String interHash, final D discussionItem, final DBSession session) { this.prepareComment(discussionItem.getUser(), discussionItem.getGroups(), session); this.getCommentDatabaseManager(discussionItem).createDiscussionItemForResource(interHash, discussionItem, session); } @SuppressWarnings("unchecked") private <D extends DiscussionItem> DiscussionItemDatabaseManager<D> getCommentDatabaseManager( final DiscussionItem discussionItem) { return (DiscussionItemDatabaseManager<D>) this.allDiscussionManagers.get(discussionItem.getClass()); } /* * (non-Javadoc) * @see org.bibsonomy.model.logic.DiscussionLogicInterface#updateDiscussionItem(java.lang.String, java.lang.String, org.bibsonomy.model.DiscussionItem) */ @Override public void updateDiscussionItem(final String username, final String interHash, final DiscussionItem discussionItem) { this.permissionDBManager.ensureIsAdminOrSelf(this.loginUser, username); final DBSession session = this.openSession(); try { final User commentUser = this.userDBManager.getUserDetails(username, session); discussionItem.setUser(commentUser); this.updateCommentForUser(interHash, discussionItem, session); } finally { session.close(); } } private <D extends DiscussionItem> void updateCommentForUser(final String interHash, final D discussionItem, final DBSession session) { this.prepareComment(discussionItem.getUser(), discussionItem.getGroups(), session); this.getCommentDatabaseManager(discussionItem).updateDiscussionItemForResource(interHash, discussionItem.getHash(), discussionItem, session); } /* * (non-Javadoc) * @see org.bibsonomy.model.logic.DiscussionLogicInterface#deleteDiscussionItem(java.lang.String, java.lang.String, java.lang.String) */ @Override public void deleteDiscussionItem(final String username, final String interHash, final String commentHash) { this.permissionDBManager.ensureIsAdminOrSelf(this.loginUser, username); final DBSession session = this.openSession(); try { final User user = this.userDBManager.getUserDetails(username, session); for (final DiscussionItemDatabaseManager<? extends DiscussionItem> discussionItemManager : this.allDiscussionManagers .values()) { if (discussionItemManager.deleteDiscussionItemForResource(interHash, user, commentHash, session)) { return; } } } finally { session.close(); } } }