Skip to content

Commit

Permalink
Merge pull request AY2425S1-CS2103T-F14a-4#182 from chrisjohntan/add-…
Browse files Browse the repository at this point in the history
…tag-manager

Implement tag manager
  • Loading branch information
yooplo authored Nov 2, 2024
2 parents 4670c1c + 7cb08cf commit 99dde99
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/main/java/seedu/address/model/CampusConnect.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public void removePersonTag(Person p, Tag t) {
/**
* Adds a new Tag to person
*/
public void addPersonTags(Person p, Set<? extends Tag> tagList) {
public void addPersonTags(Person p, Set<Tag> tagList) {
persons.addPersonTags(p, tagList);
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public interface Model {
/**
* Adds a set of tag to person
*/
void addPersonTags(Person p, Set<? extends Tag>t);
void addPersonTags(Person p, Set<Tag>t);

/**
* Adds the given person.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void deletePersonTag(Person p, Tag t) {
}

@Override
public void addPersonTags(Person p, Set<? extends Tag> t) {
public void addPersonTags(Person p, Set<Tag> t) {
campusConnect.addPersonTags(p, t);
refreshTagList();
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/seedu/address/model/person/Person.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ public Person addTag(Set<? extends Tag> tagSet) {
return new Person(this.name, this.phone, this.email, newTagSet);
}

/**
* Overwrites the person's tag set.
*/
public Person setAllTags(Set<Tag> tagSet) {
return new Person(this.name, this.phone, this.email, tagSet);
}

/**
* Returns true if person contain any tag in the new tag set.
*/
Expand Down
71 changes: 48 additions & 23 deletions src/main/java/seedu/address/model/person/UniquePersonList.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
Expand All @@ -14,6 +15,7 @@
import seedu.address.model.person.exceptions.PersonNotFoundException;
import seedu.address.model.tag.Tag;
import seedu.address.model.tag.TagCategory;
import seedu.address.model.tag.TagManager;

/**
* A list of persons that enforces uniqueness between its elements and does not allow nulls.
Expand All @@ -31,6 +33,7 @@ public class UniquePersonList implements Iterable<Person> {
private final ObservableList<Person> internalList = FXCollections.observableArrayList();
private final ObservableList<Person> internalUnmodifiableList =
FXCollections.unmodifiableObservableList(internalList);
private final TagManager tagManager = new TagManager();

/**
* Returns true if the list contains an equivalent person as the given argument.
Expand All @@ -49,6 +52,8 @@ public void add(Person toAdd) {
if (contains(toAdd)) {
throw new DuplicatePersonException();
}
Set<Tag> trackedTags = addTagsToManager(toAdd.getTags());
toAdd = toAdd.setAllTags(trackedTags);
internalList.add(toAdd);
}

Expand All @@ -61,9 +66,23 @@ public void add(int ind, Person toAdd) {
if (contains(toAdd)) {
throw new DuplicatePersonException();
}
Set<Tag> trackedTags = addTagsToManager(toAdd.getTags());
toAdd = toAdd.setAllTags(trackedTags);
internalList.add(ind, toAdd);
}

/**
* Adds tags to the tagManager to be tracked.
* Returns a set of tracked tag objects.
*/
private Set<Tag> addTagsToManager(Set<Tag> tagSet) {
Set<Tag> deduplicatedTags = new HashSet<>();
for (Tag tag : tagSet) {
Tag trackedTag = tagManager.getOrCreateTag(tag.tagName);
deduplicatedTags.add(trackedTag);
}
return deduplicatedTags;
}

/**
* Replaces the person {@code target} in the list with {@code editedPerson}.
Expand All @@ -81,6 +100,9 @@ public void setPerson(Person target, Person editedPerson) {
if (!target.isSamePerson(editedPerson) && contains(editedPerson)) {
throw new DuplicatePersonException();
}
tagManager.removeTagOccurrence(target.getTags());
Set<Tag> trackedTags = addTagsToManager(editedPerson.getTags());
editedPerson = editedPerson.setAllTags(trackedTags);

internalList.set(index, editedPerson);
}
Expand All @@ -94,6 +116,7 @@ public void remove(Person toRemove) {
if (!internalList.remove(toRemove)) {
throw new PersonNotFoundException();
}
tagManager.removeTagOccurrence(toRemove.getTags());
}

public void setPersons(UniquePersonList replacement) {
Expand All @@ -110,7 +133,12 @@ public void setPersons(List<Person> persons) {
if (!personsAreUnique(persons)) {
throw new DuplicatePersonException();
}

tagManager.clearAllTags();
List<Person> newPersons = new ArrayList<>();
for (Person p : persons) {
Set<Tag> trackedTags = tagManager.getOrCreateTag(p.getTags());
newPersons.add(p.setAllTags(trackedTags));
}
internalList.setAll(persons);
}

Expand All @@ -119,19 +147,34 @@ public void setPersons(List<Person> persons) {
*/
public void deletePersonTag(Person p, Tag t) {
requireNonNull(p);
System.out.println("here" + t);
Person replace = p.removeTag(t);
// NOTE: no need to remove tag from tagManager here, setPerson takes care of it.
setPerson(p, replace);
}

/**
* Adds a set of tag to a person.
*/
public void addPersonTags(Person p, Set<? extends Tag> t) {
public void addPersonTags(Person p, Set<Tag> t) {
requireNonNull(p);
Person replace = p.addTag(t);
// remove tags already added to p
Set<Tag> uniqueTags = filterUniqueTags(p.getTags(), t);
Set<Tag> trackedTags = tagManager.getOrCreateTag(uniqueTags);
Person replace = p.addTag(trackedTags);
setPerson(p, replace);
}

private Set<Tag> filterUniqueTags(Set<Tag> fixed, Set<Tag> toFilter) {
Set<Tag> uniqueTags = new HashSet<>();
for (Tag t : toFilter) {
if (!fixed.contains(t)) {
uniqueTags.add(t);
}
}
return uniqueTags;
}

/**
* Returns the backing list as an unmodifiable {@code ObservableList}.
*/
Expand All @@ -143,11 +186,7 @@ public ObservableList<Person> asUnmodifiableObservableList() {
* Returns the tag list of the Persons recorded
*/
public ObservableList<Tag> asTagList() {
Set<Tag> tagSet = new HashSet<>();
for (Person person : internalList) {
tagSet.addAll(person.getTags());
}
return FXCollections.observableArrayList(tagSet);
return FXCollections.observableArrayList(tagManager.asTagList());
}

/**
Expand All @@ -156,21 +195,7 @@ public ObservableList<Tag> asTagList() {
* @param cat updated {@code TagCategory}
*/
public void updateTagCategory(Tag t, TagCategory cat) {
t.setTagCategory(cat);
for (Person person : internalList) {
Set<Tag> tagSet = person.getTags();
if (tagSet.contains(t)) {
replacePersonTag(person, t, cat);
}
}
}

private void replacePersonTag(Person p, Tag t, TagCategory cat) {
Set<Tag> tagsToReplace = new HashSet<>();
tagsToReplace.add(new Tag(t.tagName, cat));
Person replace = p.removeTag(t);
replace = replace.addTag(tagsToReplace);
setPerson(p, replace);
tagManager.setTagCategory(t.tagName, cat);
}

@Override
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/seedu/address/model/tag/Tag.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class Tag {

public final String tagName;
private TagCategory tagCategory;
private int occurrences = 0;

/**
* Constructs a {@code Tag}.
Expand All @@ -36,7 +37,7 @@ public Tag(String tagName, TagCategory category) {
requireNonNull(tagName);
checkArgument(isValidTagName(tagName), MESSAGE_CONSTRAINTS);
this.tagName = tagName;
this.tagCategory = TagCategory.GENERAL;
this.tagCategory = category;
}

/**
Expand Down Expand Up @@ -70,7 +71,23 @@ public String getTagColour() {
return this.tagCategory.getColorCode();
}

public int getOccurrences() {
return occurrences;
}

/**
* Tncrease the recorded occurrences by 1.
*/
public void incrementOccurrences() {
occurrences = occurrences + 1;
}

/**
* Decrease the recorded occurrences by 1.
*/
public void decrementOccurrences() {
occurrences = occurrences - 1;
}

@Override
public boolean equals(Object other) {
Expand Down
128 changes: 128 additions & 0 deletions src/main/java/seedu/address/model/tag/TagManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package seedu.address.model.tag;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
* The manager of all the tags currently being used.
*/
public class TagManager {

private final HashMap<String, Tag> tagMap;

/**
* Constructs a new TagManager to track Tag usages.
*/
public TagManager() {
this.tagMap = new HashMap<>();
}

/**
* Returns true if the Tag is being tracked in the TagManager.
*/
public boolean containsTag(Tag t) {
String tagName = t.tagName;
return tagMap.containsKey(tagName);
}

/**
* Returns the Tag with the corresponding tag name.
* If the tag already exists, return the stored tag object.
* Else if the tag does not yet exist, create a new tag and return it. <br>
* <strong>Warning:</strong> only use this method if you want to add or increase tag tracking.
* @param tagName String of the tag name
* @return The new or existing tag with the corresponding tag name
*/
public Tag getOrCreateTag(String tagName) {

Tag tagToIncrement = tagMap.computeIfAbsent(tagName, Tag::new);
System.out.println("tracking " + tagToIncrement.tagName + "(" + tagToIncrement.getTagCategory() + ")");
tagToIncrement.incrementOccurrences();
// System.out.println(tagToIncrement.usages);
System.out.println(tagMap.values());
return tagToIncrement;
}

/**
* Returns a set of tags that are being tracked by TagManager, corresponding to the input set.
*/
public Set<Tag> getOrCreateTag(Set<Tag> tags) {
Set<Tag> trackedSet = new HashSet<>();
for (Tag t : tags) {
String tagName = t.tagName;
trackedSet.add(getOrCreateTag(tagName));
}
return trackedSet;
}

/**
* Reduces the usage count of the tag and removes it if no more occurrences remain.
*/
public void removeTagOccurrence(Tag t) {
String tagName = t.tagName;
Tag tagToDecrement = tagMap.get(tagName);
assert tagToDecrement != null;
System.out.println("huh" + tagToDecrement);
if (tagToDecrement.getOccurrences() <= 1) {
System.out.println("removed");
tagMap.remove(tagToDecrement.tagName);
return;
}
tagToDecrement.decrementOccurrences();
}

/**
* Reduces the usage count of each tag in the given set and removes it if no more occurrences remain.
*/
public void removeTagOccurrence(Set<Tag> tags) {
for (Tag t : tags) {
removeTagOccurrence(t);
}
}

/**
* Returns the stored category of the tag with same label as the passed {@code Tag t}.
*/
public TagCategory getTagCategory(Tag t) {
String tagName = t.tagName;
return tagMap.get(tagName).getTagCategory();
}

/**
* Set the category of a tag.
* Assumes that the tag already exists in the TagManager.
*/
public void setTagCategory(String tagName, TagCategory cat) {
System.out.println(cat);
Tag tag = tagMap.get(tagName);
tag.setTagCategory(cat);
System.out.println(tagMap.get(tagName).getTagCategory());
}

/**
* Clears the TagManager of all stored tags to an empty state.
*/
public void clearAllTags() {
tagMap.clear();
}

/**
* Remove all the tags from the passed set, regardless of how many occurrences remain.
* @see TagManager#removeTagOccurrence(Set) removeTagOccurrence
*/
public void removeTags(Set<Tag> tagSet) {
for (Tag t : tagSet) {
tagMap.remove(t.tagName);
}
}

/**
* Returns the existing tags as a Collection.
*/
public Collection<Tag> asTagList() {
return tagMap.values();
}

}
4 changes: 3 additions & 1 deletion src/main/java/seedu/address/ui/PersonCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ public PersonCard(Person person, int displayedIndex) {
email.setText(person.getEmail().value);
person.getTags().stream()
.sorted(Comparator.comparing(tag -> tag.tagName))
.forEach(tag -> tags.getChildren().add(new Label(tag.tagName)));
// Tag category displayed for visual testing
// TODO: remove tag category text display after implementing colour code
.forEach(tag -> tags.getChildren().add(new Label(tag.tagName + " " + tag.getTagCategory())));

// add horizontal and vertical gaps for the tags FlowPane
tags.setHgap(5);
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/seedu/address/ui/TagCard.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class TagCard extends UiPart<Region> {
public TagCard(Tag tag, int displayedIndex) {
super(FXML);
this.tag = tag;
tagName.setText((displayedIndex + 1) + ". " + tag.tagName);
// Tag category displayed for visual testing
// TODO: remove tag category text display after implementing colour code
tagName.setText((displayedIndex + 1) + ". " + tag.tagName + "(" + tag.getTagCategory() + ")");
}
}
Loading

0 comments on commit 99dde99

Please sign in to comment.