package marubinotto.piggydb.model.entity; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import marubinotto.piggydb.model.Classifiable; import marubinotto.piggydb.model.Classification; import marubinotto.piggydb.model.MutableClassification; import marubinotto.piggydb.model.Tag; import marubinotto.piggydb.model.TagRepository; import marubinotto.piggydb.model.auth.User; import marubinotto.piggydb.model.exception.AuthorizationException; import marubinotto.piggydb.model.exception.InvalidTaggingException; import marubinotto.util.Assert; public abstract class RawClassifiable extends RawEntity implements Classifiable { private MutableClassification classification = new MutableClassification(this); public RawClassifiable() { } public RawClassifiable(User user) { super(user); } public Classification getClassification() { return this.classification; } public MutableClassification getMutableClassification() { return this.classification; } // // Authorization // public final boolean canChangeClassification(User user) { Assert.Arg.notNull(user, "user"); try { ensureCanChangeClassification(user); return true; } catch (AuthorizationException e) { return false; } } public final boolean canAddTag(Tag tag, User user) { Assert.Arg.notNull(tag, "tag"); Assert.Arg.notNull(user, "user"); try { ensureCanAddTag(tag, user); return true; } catch (AuthorizationException e) { return false; } } public final boolean canAddTag(String tagName, User user) { Assert.Arg.notNull(tagName, "tagName"); Assert.Arg.notNull(user, "user"); return canAddTag(new RawTag(tagName), user); } public final boolean canRemoveTag(Tag tag, User user) { Assert.Arg.notNull(tag, "tag"); Assert.Arg.notNull(user, "user"); try { ensureCanRemoveTag(tag, user); return true; } catch (AuthorizationException e) { return false; } } protected void ensureCanChangeClassification(User user) throws AuthorizationException { ensureCanChange(user); } protected void ensureCanAddTag(Tag tag, User user) throws AuthorizationException { ensureCanChangeClassification(user); RawTag.ensureCanUse(tag, user); } protected void ensureCanRemoveTag(Tag tag, User user) throws AuthorizationException { ensureCanChangeClassification(user); RawTag.ensureCanUse(tag, user); } // // Update // public void addTagByUser(Tag tag, User user) throws InvalidTaggingException { Assert.Arg.notNull(tag, "tag"); Assert.Arg.notNull(user, "user"); // Avoid an auth error when the classification won't be changed if (this.classification.containsTagName(tag.getName())) return; ensureCanAddTag(tag, user); this.classification.addTag(tag); onPropertyChange(user); } public final void addTagByUser(String name, TagRepository tagRepository, User user) throws InvalidTaggingException, Exception { Assert.Arg.notNull(name, "name"); Assert.Arg.notNull(tagRepository, "tagRepository"); Assert.Arg.notNull(user, "user"); addTagByUser(tagRepository.getOrCreateTag(name, user), user); } public final void updateTagsByUser( Collection<String> tagNames, TagRepository tagRepository, User user) throws InvalidTaggingException, Exception { Assert.Arg.notNull(tagNames, "tagNames"); Assert.Arg.notNull(tagRepository, "tagRepository"); Assert.Arg.notNull(user, "user"); Classification newTags = selectMostConcreteTags(tagNames, tagRepository, user); Set<String> originalTags = new HashSet<String>(this.classification.getTagNames()); for (Tag newTag : newTags) { addTagByUser(newTag, user); originalTags.remove(newTag.getName()); } for (String tagToRemove : originalTags) { // the remains should be deleted removeTagByUser(tagToRemove, user); } } public static MutableClassification selectMostConcreteTags( Collection<String> tagNames, TagRepository tagRepository, User user) throws Exception { MutableClassification classification = new MutableClassification(); for (String name : tagNames) { if (!classification.isSubordinateOf(name)) { classification.addTag(tagRepository.getOrCreateTag(name, user)); } } return classification; } public void removeTagByUser(String name, User user) { Assert.Arg.notNull(name, "name"); Assert.Arg.notNull(user, "user"); Tag tag = this.classification.getTag(name); if (tag == null) return; ensureCanRemoveTag(tag, user); this.classification.removeTag(name); onPropertyChange(user); } public void removeTagsByUserClassifiedAs(String tagName, User user) { Assert.Arg.notNull(tagName, "tagName"); Assert.Arg.notNull(user, "user"); removeTagByUser(tagName, user); for (Tag tag : this.classification) { if (tag.getClassification().isSubordinateOf(tagName)) removeTagByUser(tag.getName(), user); } } public void syncClassificationWith(Classifiable classifiable) throws InvalidTaggingException { Assert.Arg.notNull(classifiable, "classifiable"); getMutableClassification().syncWith(classifiable.getClassification()); } public static void refreshEachTag( List<? extends RawClassifiable> classifiables, TagRepository tagRepository) throws Exception { for (RawClassifiable classifiable : classifiables) { classifiable.getMutableClassification().refreshEachTag(tagRepository); } } }