Skip to content

Commit

Permalink
Support for user favorites. (#402)
Browse files Browse the repository at this point in the history
* Implemented CRUD operation for tags.

* Implemented tag association to the resource.

* Added test for tag management.

* Added log messages.

* Added DB creation scripts for tag tables.

* Added javadoc to tag REST service.

* Refactoring.

* Added count in get all tags operation result.

* Added filtering by tag for the extJS get all operation.

* Exposed get all tags operation to anonymous users.

* Refactored nameLike path variable handling.

* Introduced AssociatedEntityFilter abstraction.

* Set distinct in resource count query.

* Added null check to nameLike path variable handling.

* Refactored nameLike query variable handling.

* Added DB migration scripts.

* Handled on delete cascade actions on tags.

* Implementation for user favorites functionality.

* Added favorite only resource search to ExtJS resource list operation.

* Renamed deprecated functions in ResourceService.

* Added DB migration scripts.

* Added favorite information to extJS resource get operations.

* Fixed hash calculation for StoredData to avoid stack overflow.

* Fixed bug that was removing tag association after updates.

* Signalled failing assertion in rest client test.

* Fixed tag list serialization when null.

* Handled names in filters that contain commas.

* Fixes after merging master.
  • Loading branch information
axl8713 authored Feb 6, 2025
1 parent 703c5e4 commit 257d342
Show file tree
Hide file tree
Showing 28 changed files with 908 additions and 136 deletions.
17 changes: 17 additions & 0 deletions doc/sql/002_create_schema_oracle.sql
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,23 @@
foreign key (tag_id)
references gs_tag(id);

create table gs_user_favorites (
user_id number(19,0) not null,
resource_id number(19,0) not null,
primary key (user_id, resource_id)
);

alter table gs_user_favorites
add constraint fk_user_favorites_resource
foreign key (resource_id)
references gs_resource(id)
on delete cascade;

alter table gs_user_favorites
add constraint fk_user_favorites_user
foreign key (user_id)
references gs_user(id);

create index idx_attribute_name on gs_attribute (name);

create index idx_attribute_resource on gs_attribute (resource_id);
Expand Down
19 changes: 18 additions & 1 deletion doc/sql/002_create_schema_postgres.sql
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,24 @@ SET search_path TO geostore;
add constraint fk_resource_tags_tag
foreign key (tag_id)
references gs_tag(id);


create table gs_user_favorites (
user_id int8 not null,
resource_id int8 not null,
constraint gs_user_favorites_pkey primary key (user_id, resource_id)
);

alter table gs_user_favorites
add constraint fk_user_favorites_resource
foreign key (resource_id)
references gs_resource(id)
on delete cascade;

alter table gs_user_favorites
add constraint fk_user_favorites_user
foreign key (user_id)
references gs_user(id);

create index idx_attribute_name on gs_attribute (name);

create index idx_attribute_resource on gs_attribute (resource_id);
Expand Down
23 changes: 18 additions & 5 deletions doc/sql/migration/h2/h2-migration-from-v.2.1.0-to-v2.3.0.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-- Tags
CREATE TABLE gs_tag (
id BIGINT NOT NULL,
color VARCHAR(255) NOT NULL,
Expand All @@ -12,14 +13,26 @@ CREATE TABLE gs_resource_tags (
CONSTRAINT gs_resource_tags_pkey PRIMARY KEY (tag_id, resource_id)
);

-- Add foreign key constraints to gs_resource_tags
ALTER TABLE gs_resource_tags
ADD CONSTRAINT fk_resource_tags_resource
FOREIGN KEY (resource_id)
REFERENCES gs_resource(id)
ON DELETE CASCADE;

ALTER TABLE gs_resource_tags
ADD CONSTRAINT fk_resource_tags_tag
FOREIGN KEY (tag_id)
REFERENCES gs_tag(id);
-- Favorites
CREATE TABLE gs_user_favorites (
user_id BIGINT NOT NULL,
resource_id BIGINT NOT NULL,
CONSTRAINT gs_user_favorites_pkey PRIMARY KEY (user_id, resource_id)
);

ALTER TABLE gs_user_favorites
ADD CONSTRAINT fk_user_favorites_resource
FOREIGN KEY (resource_id)
REFERENCES gs_resource(id)
ON DELETE CASCADE;

ALTER TABLE gs_user_favorites
ADD CONSTRAINT fk_user_favorites_user
FOREIGN KEY (user_id)
REFERENCES gs_user(id);
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-- Tags
create table gs_tag (
id number(19,0) not null,
color varchar2(255 char) not null,
Expand All @@ -12,7 +13,6 @@ create table gs_resource_tags (
primary key (tag_id, resource_id)
);

-- Add foreign key constraints to gs_resource_tags
alter table gs_resource_tags
add constraint fk_resource_tags_resource
foreign key (resource_id)
Expand All @@ -22,4 +22,22 @@ alter table gs_resource_tags
alter table gs_resource_tags
add constraint fk_resource_tags_tag
foreign key (tag_id)
references gs_tag(id);
references gs_tag(id);

-- Favorites
create table gs_user_favorites (
user_id number(19,0) not null,
resource_id number(19,0) not null,
primary key (user_id, resource_id)
);

alter table gs_user_favorites
add constraint fk_user_favorites_resource
foreign key (resource_id)
references gs_resource(id)
on delete cascade;

alter table gs_user_favorites
add constraint fk_user_favorites_user
foreign key (user_id)
references gs_user(id);
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-- Tags
create table gs_tag (
id int8 not null,
color varchar(255) not null,
Expand All @@ -12,7 +13,6 @@ create table gs_resource_tags (
constraint gs_resource_tags_pkey primary key (tag_id, resource_id)
);

-- Add foreign key constraints to gs_resource_tags
alter table gs_resource_tags
add constraint fk_resource_tags_resource
foreign key (resource_id)
Expand All @@ -22,4 +22,22 @@ alter table gs_resource_tags
alter table gs_resource_tags
add constraint fk_resource_tags_tag
foreign key (tag_id)
references gs_tag(id);
references gs_tag(id);

-- Favorites
create table gs_user_favorites (
user_id int8 not null,
resource_id int8 not null,
constraint gs_user_favorites_pkey primary key (user_id, resource_id)
);

alter table gs_user_favorites
add constraint fk_user_favorites_resource
foreign key (resource_id)
references gs_resource(id)
on delete cascade;

alter table gs_user_favorites
add constraint fk_user_favorites_user
foreign key (user_id)
references gs_user(id);
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ public class Resource implements Serializable, CycleRecoverable {
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<Tag> tags;

@ManyToMany(mappedBy = "favorites", fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<User> favoritedBy;

/** @return the id */
public Long getId() {
return id;
Expand Down Expand Up @@ -268,6 +272,14 @@ public void setTags(Set<Tag> tags) {
this.tags = tags;
}

public Set<User> getFavoritedBy() {
return favoritedBy;
}

public void setFavoritedBy(Set<User> favoritedBy) {
this.favoritedBy = favoritedBy;
}

/*
* (non-Javadoc) @see java.lang.Object#toString()
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,8 @@
@XmlRootElement(name = "User")
public class User implements Serializable {

/** The Constant serialVersionUID. */
private static final long serialVersionUID = -138056245004697133L;

/** The id. */
@Id @GeneratedValue private Long id;

@Column(nullable = false, updatable = false, length = 255)
Expand All @@ -90,20 +88,12 @@ public class User implements Serializable {
@Enumerated(EnumType.STRING)
private Role role;

public User() {};

public User(User user) {
this.id = user.id;
this.name = user.name;
this.password = user.password;
this.role = user.role;
this.newPassword = user.newPassword;
this.trusted = user.trusted;
this.attribute = user.attribute;
this.security = user.security;
this.groups = user.groups;
this.enabled = user.enabled;
}
@ManyToMany
@JoinTable(
name = "gs_user_favorites",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "resource_id"))
private Set<Resource> favorites;

/*
* NOT to be saved on DB
Expand Down Expand Up @@ -134,6 +124,21 @@ public User(User user) {
@Column(nullable = false, updatable = true)
private boolean enabled = true;

public User() {};

public User(User user) {
this.id = user.id;
this.name = user.name;
this.password = user.password;
this.role = user.role;
this.newPassword = user.newPassword;
this.trusted = user.trusted;
this.attribute = user.attribute;
this.security = user.security;
this.groups = user.groups;
this.enabled = user.enabled;
}

/** @return the id */
// @XmlTransient
public Long getId() {
Expand Down Expand Up @@ -275,6 +280,14 @@ public void setTrusted(boolean trusted) {
this.trusted = trusted;
}

public Set<Resource> getFavorites() {
return favorites;
}

public void setFavorites(Set<Resource> favorites) {
this.favorites = favorites;
}

/*
* (non-Javadoc) @see java.lang.Object#toString()
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@ public interface ResourceDAO extends RestrictedGenericDAO<Resource> {
* @param resourceId
* @return List<Attribute>
*/
public List<Attribute> findAttributes(long resourceId);
List<Attribute> findAttributes(long resourceId);

/** @param search */
public void removeResources(ISearch search);
void removeResources(ISearch search);

/** @param resourcesIDs A list of resources Ids to search */
public List<Resource> findResources(List<Long> resourcesIds);
/** @param resourcesIds A list of resources Ids to search */
List<Resource> findResources(List<Long> resourcesIds);

/**
* Gets a resource by name.
*
* @return the resource with the specified name, or null if none was found
* @throws NonUniqueResultException if more than one result
*/
public Resource findByName(String resourceName);
Resource findByName(String resourceName);

/**
* Returns a list of resource names matching the specified pattern
Expand All @@ -67,4 +67,12 @@ public interface ResourceDAO extends RestrictedGenericDAO<Resource> {
* @return a list of resource names
*/
public List<String> findResourceNamesMatchingPattern(String pattern);

/**
* Returns a list of resources that are the favorites of the user
*
* @param userId user identifier
* @return a list of resources favorites by the user
*/
List<Resource> findUserFavorites(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,17 @@ public List<String> findResourceNamesMatchingPattern(String pattern) {

return resourceNames;
}

/**
* @param userId
* @return List<Resource> the user's favorite resources
*/
@Override
public List<Resource> findUserFavorites(Long userId) {
Search searchCriteria = new Search(Resource.class);

searchCriteria.addFilter(Filter.some("favoritedBy", Filter.equal("id", userId)));

return super.search(searchCriteria);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* ====================================================================
*
* Copyright (C) 2025 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.
*
* ====================================================================
*
* This software consists of voluntary contributions made by developers
* of GeoSolutions. For more information on GeoSolutions, please see
* <http://www.geo-solutions.it/>.
*
*/
package it.geosolutions.geostore.services;

import it.geosolutions.geostore.services.exception.NotFoundServiceEx;

public interface FavoriteService {

void addFavorite(long userId, long resourceId) throws NotFoundServiceEx;

void removeFavorite(long userId, long resourceId) throws NotFoundServiceEx;
}
Loading

0 comments on commit 257d342

Please sign in to comment.