samuelchassot/SDP-SwissTeam

View on GitHub
app/src/main/java/ch/epfl/swissteam/services/models/User.java

Summary

Maintainability
D
1 day
Test Coverage
package ch.epfl.swissteam.services.models;

import android.util.Log;

import com.google.firebase.database.DatabaseReference;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import ch.epfl.swissteam.services.providers.DBUtility;
import ch.epfl.swissteam.services.utils.Utils;

/**
 * Class representing a user in the database
 *
 * @author simonwicky
 */
public class User implements DBSavable {

    public static String DELETED_USER_NAME = "Deleted user";
    public static String DELETED_USER_IMG_URL = "https://cdn.pixabay.com/photo/2014/03/25/15/19/cross-296507_960_720.png";

    private String googleId_, email_, name_, description_, imageUrl_;
    private int rating_;
    private double latitude_, longitude_;
    private ArrayList<Categories> categories_;
    private HashMap<String, ArrayList<String>> keyWords_;
    private ArrayList<String> upvotes_;
    private ArrayList<String> downvotes_;

    private ArrayList<ChatRelation> chatRelations_;
    private boolean isShownLocation_;

    public enum Vote{
        UPVOTE,
        DOWNVOTE
    }

    public static int RATING_[] = {-2,-1,0,1,2};

    /**
     * return the GoogleID that corresponds to a deleted user
     *
     * @return the deleted user's GoogleID
     */
    public static String getDeletedUserGoogleID() {
        return "000000000000000000000";
    }

    /**
     * return a deleted user
     *
     * @return a deleted user
     */
    public static User getDeletedUser() {
        User deletedUser = new User(getDeletedUserGoogleID(), DELETED_USER_NAME,
                "", "", new ArrayList<>(), new HashMap<>(), new ArrayList<>(),
                DELETED_USER_IMG_URL,0, 0.0, 0.0, new ArrayList<>(), new ArrayList<>(), false);
        return deletedUser;
    }

    /**
     * Default constructor, needed for database
     */
    public User() {
        categories_ = new ArrayList<>();
        chatRelations_ = new ArrayList<>();
        keyWords_ = new HashMap<>();
        downvotes_ = new ArrayList<>();
        upvotes_ = new ArrayList<>();
    }


    /**
     * Create a new user given its specificities
     *
     * @param googleID_      User's unique googleId
     * @param name_          User's name
     * @param email_         User's email
     * @param description_   User's description
     * @param categories_    User's categories of services
     * @param keyWords_      User's keywords for each Categories
     * @param chatRelations_ User's chat relations
     * @param rating_        User's rating score
     * @param latitude_      User's last latitude
     * @param longitude_     User's last longitude
     * @param isShownLocation_   User's choice to show his location
     */

    public User(String googleID_, String name_, String email_, String description_,
                ArrayList<Categories> categories_,
                HashMap<String, ArrayList<String>> keyWords_,
                ArrayList<ChatRelation> chatRelations_,
                String imageUrl_, int rating_, double latitude_, double longitude_,
                ArrayList<String> upvotes_, ArrayList<String> downvotes_, boolean isShownLocation_) {
        this.googleId_ = googleID_;
        this.email_ = email_;
        this.name_ = name_;
        this.description_ = description_;
        this.imageUrl_ = imageUrl_;
        this.rating_ = rating_;
        this.categories_ = categories_ == null ? new ArrayList<>() : new ArrayList<>(categories_);

        //keywords are stored in lowercase to simplify the comparison when searching for services
        HashMap<String, ArrayList<String>> lowercaseKeywords = new HashMap<>();
        if(keyWords_ != null) {
            ArrayList<String> kwList;
            for (String key : keyWords_.keySet()) {
                kwList = new ArrayList<>();
                for (String k : keyWords_.get(key)) {
                    kwList.add(k.toLowerCase());
                }
                lowercaseKeywords.put(key, kwList);
            }
        }
        this.keyWords_ = lowercaseKeywords;

        this.chatRelations_ = chatRelations_ == null ? new ArrayList<>() :  new ArrayList<>(chatRelations_);
        this.upvotes_ = upvotes_ == null ? new ArrayList<>() :  new ArrayList<>(upvotes_);
        this.downvotes_ = downvotes_ == null ? new ArrayList<>() :  new ArrayList<>(downvotes_);
        this.latitude_ = latitude_;
        this.longitude_ = longitude_;
        this.isShownLocation_ = isShownLocation_;
    }


    /**
     * Gives the google id of the user
     *
     * @return the google id of the user
     */
    public String getGoogleId_() {
        return googleId_;
    }

    /**
     * Gives the name of the user
     *
     * @return the name of the user
     */
    public String getName_() {
        return name_;
    }

    /**
     * Gives the email of the user
     *
     * @return the email of the user
     */
    public String getEmail_() {
        return email_;
    }

    /**
     * Gives the description of the user
     *
     * @return the description of the user
     */
    public String getDescription_() {
        return description_;
    }

    /**
     * Gives the url of the image of the user
     *
     * @return the url of the image of the user
     */
    public String getImageUrl_() {
        return imageUrl_;
    }

    /**
     * Gives the rating of the user
     *
     * @return the rating of the user
     */
    public int getRating_() {
        return rating_;
    }

    /**
     * Gives the latitude of the user
     *
     * @return the latitude of the user
     */
    public double getLatitude_() {
        return latitude_;
    }

    /**
     * Gives the longitude of the user
     *
     * @return the longitude of the user
     */
    public double getLongitude_() {
        return longitude_;
    }

    /**
     * Gives the choice of the user to show his location
     *
     * @return if the user wants to show his location
     */
    public boolean getIsShownLocation_() {
        return isShownLocation_;
    }

    /**
     * Gives the list of categories of the user if it exists, creates a new empty list otherwise
     *
     * @return the list of categories of the user
     */
    public ArrayList<Categories> getCategories_() {
        if (categories_ == null) {
            return new ArrayList<>();
        }
        return new ArrayList<>(categories_);
    }

    /**
     * Gives the Map of keywords for each categories the User has in his Categories
     * If the USer hadn't put any keywords for a given categories, it will not appear in the Map
     *
     * @return the map of keywords for each categories
     */
    public HashMap<String, ArrayList<String>> getKeyWords_() {
        if(keyWords_ != null){
            return new HashMap<>(keyWords_);
        }
        return new HashMap<>();




    }

    /**
     * Gives the List<String> of keywords the user has for the given Categories
     *
     * @param c
     * @return ArrayList<String> of keyWords (can be empty)
     */
    public ArrayList<String> getKeyWords(Categories c) {
        ArrayList<String> kWords = new ArrayList<>();
        if (keyWords_.containsKey(c.toString())) {
            kWords.addAll(keyWords_.get(c.toString()));
        }
        return kWords;
    }

    /**
     * Gives the list of chat relations of the user if it exists, creates a new empty list otherwise
     *
     * @return the list of categories of the user
     */
    public ArrayList<ChatRelation> getChatRelations_() {
        if (chatRelations_ == null) {
            return new ArrayList<>();
        }
        return new ArrayList<>(chatRelations_);
    }

    /**
     * Gives the list of users who upvoted this user
     *
     * @return the list of upvotes of the user
     */
    public ArrayList<String> getUpvotes_() {
        if (upvotes_ == null) {
            return new ArrayList<>();
        }
        return new ArrayList<>(upvotes_);
    }

    /**
     * Gives the list of users who downvoted this user
     *
     * @return the list of downvotes of the user
     */
    public ArrayList<String> getDownvotes_() {
        if (downvotes_ == null) {
            return new ArrayList<>();
        }
        return new ArrayList<>(downvotes_);
    }

    /**
     * Add the user to a database
     *
     * @param db the database in which to add the user
     */
    public void addToDB(DatabaseReference db) {
        db.child(DBUtility.USERS).child(googleId_).setValue(this);
        if (categories_ != null) {
            for (Categories category : categories_) {
                db.child(DBUtility.CATEGORIES).child(category.toString()).child(googleId_).setValue("true");
            }
        }

        Log.i("USER", "ADDED");
    }

    @Override
    public void removeFromDB(DatabaseReference db) throws Utils.IllegalCallException {
        //remove the user's entry
        db.child(DBUtility.USERS).child(googleId_).removeValue();

        //remove user's from all categories
        List<Categories> allCat = new ArrayList<Categories>(Arrays.asList(Categories.values()));
        for (Categories c : allCat) {
            DBUtility.get().getCategory(c, cat -> {
                cat.removeUser(this);
                cat.addToDB(db);
            });
        }

        //remove the user from posts he/she made
        DBUtility.get().getUsersPosts(googleId_, posts -> {
            for (Post p : posts) {
                p.removeUser();
            }
        });

        //remove the user from all ChatRelations and delete the relation if both users are removed
        boolean removed = false;
        for (ChatRelation cr : chatRelations_) {
            if (cr.getFirstUserId_().equals(googleId_)) {
                if (cr.getSecondUserId_().equals(User.getDeletedUserGoogleID())) {
                    cr.removeFromDB(db);
                    removed = true;
                } else {
                    cr.setFirstUserId_(User.getDeletedUserGoogleID());
                }
            }
            if (cr.getSecondUserId_().equals(googleId_) && !removed) {
                if (cr.getFirstUserId_().equals(User.getDeletedUserGoogleID())) {
                    cr.removeFromDB(db);
                    removed = true;
                } else {
                    cr.setSecondUserId_(User.getDeletedUserGoogleID());
                }

            }
            if (!removed) {
                //change the ID in all messages the user sent
                DBUtility.get().getAllMessagesFromChatRelation(cr.getId_(), messages -> {
                    for (ChatMessage m : messages) {
                        m.setUserId_(User.getDeletedUserGoogleID());
                        m.setUser_(User.getDeletedUser().getName_());
                        m.addToDB(db);
                    }
                });
                cr.addToDB(db);
            }
        }


    }

    /**
     * Add a chatRelation to the list of chatRelationId of the user and save it into the database db
     *
     * @param chatRelation the chatRelation to add
     * @param db           reference to the database to update the user
     */
    public void addChatRelation(ChatRelation chatRelation, DatabaseReference db) {
        if (chatRelations_ == null) {
            chatRelations_ = new ArrayList<>();
        }

        if (!chatRelations_.contains(chatRelation)) chatRelations_.add(chatRelation);

        if (db != null) {
            addToDB(db);
        }
    }

    /**
     * Add a chatRelationId to the list of chatRelation of the user
     *
     * @param chatRelation the id of the chatRelation
     */
    public void addChatRelation(ChatRelation chatRelation) {
        addChatRelation(chatRelation, null);
    }

    /**
     * Remove a relation from the list of chatRelation of this user and save the user in the DB if db
     * is not null
     *
     * @param chatRelation the chatRelation to remove
     * @param db           reference to the database to update the user
     */
    public void removeChatRelation(ChatRelation chatRelation, DatabaseReference db) {
        if (chatRelations_ != null) chatRelations_.remove(chatRelation);

        if (db != null) {
            addToDB(db);
        }
    }

    /**
     * Remove a relation from the list of chatRelation of this user
     *
     * @param chatRelation the chatRelation to remove
     */
    public void removeChatRelation(ChatRelation chatRelation) {
        removeChatRelation(chatRelation, null);
    }

    @Override
    public boolean equals(Object other) {
        return this.googleId_.equals(((User) other).getGoogleId_());
    }

    /**
     * return the chatRelation that this user have with other if it exists already and null otherwise
     *
     * @param other the other user
     * @return the chatRelation that this user have with other if it exists already and null otherwise
     */
    public ChatRelation relationExists(User other) {
        return relationExists(other.getGoogleId_());
    }

    /**
     * return the chatRelation that this user have with otherID if it exists already and null otherwise
     *
     * @param otherId the other user's ID
     * @return the chatRelation that this user have with other if it exists already and null otherwise
     */
    public ChatRelation relationExists(String otherId) {
        if (chatRelations_ == null) return null;
        for (ChatRelation cR : chatRelations_) {
            if (cR.getFirstUserId_().compareTo(getGoogleId_()) == 0 && cR.getSecondUserId_().compareTo(otherId) == 0
                    || cR.getFirstUserId_().compareTo(otherId) == 0 && cR.getSecondUserId_().compareTo(getGoogleId_()) == 0) {
                return cR;
            }
        }
        return null;
    }

    public void vote(Vote vote, User user) {
        if (vote == Vote.UPVOTE) {
            this.upvote(user);
        } else if (vote == Vote.DOWNVOTE) {
            this.downvote(user);
        }
        this.addToDB(DBUtility.get().getDb_());

    }

    private void upvote(User user) {
        //If already upvoted, remove it
        if (upvotes_.contains(user.getGoogleId_())) {
            upvotes_.remove(user.getGoogleId_());
            rating_ -= 1;
            return;
        }

        //if downvoted, correct the vote
        if (downvotes_.contains(user.getGoogleId_())) {
            downvotes_.remove(user.getGoogleId_());
            //one downvote less
            rating_ += 1;
        }
        upvotes_.add(user.googleId_);
        //one upvote more
        rating_ += 1;
    }


    private void downvote(User user) {
        if (downvotes_.contains(user.getGoogleId_())) {
            downvotes_.remove(user.getGoogleId_());
            rating_ += 1;
            return;
        }

        if (upvotes_.contains(user.getGoogleId_())) {
            upvotes_.remove(user.getGoogleId_());
            //one upvote less
            rating_ -= 1;
        }
        downvotes_.add(user.googleId_);
        //one downvote more
        rating_ -= 1;
    }


}