src/main/java/org/jboss/pressgang/ccms/model/utils/TopicUtilities.java
public static void validateAndFixTags(final Topic topic) {
        /*
         * validate the tags that are applied to this topic. generally the gui should enforce these rules, with the exception of
         * the bulk tag apply function
         */

        // Create a collection of Categories mapped to TagToCategories, sorted by the Category sorting order
        final TreeMap<Category, ArrayList<TagToCategory>> tagDB = new TreeMap<Category, ArrayList<TagToCategory>>(
                Collections.reverseOrder());

        for (final TopicToTag topicToTag : topic.getTopicToTags()) {
            final Tag tag = topicToTag.getTag();
            for (final TagToCategory tagToCategory : tag.getTagToCategories()) {
                final Category category = tagToCategory.getCategory();

                if (!tagDB.containsKey(category)) tagDB.put(category, new ArrayList<TagToCategory>());

                tagDB.get(category).add(tagToCategory);
            }
        }

        // now remove conflicting tags
        for (final Category category : tagDB.keySet()) {
            /* sort by the tags position in the category */
            Collections.sort(tagDB.get(category), new TagToCategorySortingComparator(false));

            /*
             * because of the way we have ordered the tagDB collections, and the ArrayLists it contains, this process will
             * remove those tags that belong to lower priority categories, and lower priority tags in those categories
             */

            final ArrayList<TagToCategory> tagToCategories = tagDB.get(category);

            // remove tags in the same mutually exclusive categories
            if (category.isMutuallyExclusive() && tagToCategories.size() > 1) {
                while (tagToCategories.size() > 1) {
                    final TagToCategory tagToCategory = tagToCategories.get(1);
                    /* get the lower priority tag */
                    final Tag removeTag = tagToCategory.getTag();
                    /* remove it from the tagDB collection */
                    tagToCategories.remove(tagToCategory);

                    /* and remove it from the tag collection */
                    final ArrayList<TopicToTag> removeTopicToTagList = new ArrayList<TopicToTag>();
                    for (final TopicToTag topicToTag : topic.getTopicToTags()) {
                        if (topicToTag.getTag().equals(removeTag)) removeTopicToTagList.add(topicToTag);
                    }

                    for (final TopicToTag removeTopicToTag : removeTopicToTagList) {
                        topic.getTopicToTags().remove(removeTopicToTag);
                    }
                }
            }

            /* remove tags that are explicitly defined as mutually exclusive */
            for (final TagToCategory tagToCategory : tagToCategories) {
                final Tag tag = tagToCategory.getTag();
                for (final Tag exclusionTag : tag.getExcludedTags()) {
                    if (filter(having(on(TopicToTag.class).getTag(), equalTo(tagToCategory.getTag())),
                            topic.getTopicToTags()).size() != 0 && // make
                            /*
                             * sure that we have not removed this tag already
                             */
                            filter(having(on(TopicToTag.class).getTag(), equalTo(exclusionTag)),
                                    topic.getTopicToTags()).size() != 0 && // make
                            /*
                             * sure the exclusion tag exists
                             */
                            !exclusionTag.equals(tagToCategory.getTag())) // make
                    /*
                     * sure we are not trying to remove ourselves
                     */ {
                        with(topic.getTopicToTags()).remove(having(on(TopicToTag.class).getTag(), equalTo(exclusionTag)));
                    }
                }
            }
        }
    }
public static void validateAndFixTags(final Topic topic) {
        /*
         * validate the tags that are applied to this topic. generally the gui should enforce these rules, with the exception of
         * the bulk tag apply function
         */

        // Create a collection of Categories mapped to TagToCategories, sorted by the Category sorting order
        final TreeMap<Category, ArrayList<TagToCategory>> tagDB = new TreeMap<Category, ArrayList<TagToCategory>>(
                Collections.reverseOrder());

        for (final TopicToTag topicToTag : topic.getTopicToTags()) {
            final Tag tag = topicToTag.getTag();
            for (final TagToCategory tagToCategory : tag.getTagToCategories()) {
                final Category category = tagToCategory.getCategory();

                if (!tagDB.containsKey(category)) tagDB.put(category, new ArrayList<TagToCategory>());

                tagDB.get(category).add(tagToCategory);
            }
        }

        // now remove conflicting tags
        for (final Category category : tagDB.keySet()) {
            /* sort by the tags position in the category */
            Collections.sort(tagDB.get(category), new TagToCategorySortingComparator(false));

            /*
             * because of the way we have ordered the tagDB collections, and the ArrayLists it contains, this process will
             * remove those tags that belong to lower priority categories, and lower priority tags in those categories
             */

            final ArrayList<TagToCategory> tagToCategories = tagDB.get(category);

            // remove tags in the same mutually exclusive categories
            if (category.isMutuallyExclusive() && tagToCategories.size() > 1) {
                while (tagToCategories.size() > 1) {
                    final TagToCategory tagToCategory = tagToCategories.get(1);
                    /* get the lower priority tag */
                    final Tag removeTag = tagToCategory.getTag();
                    /* remove it from the tagDB collection */
                    tagToCategories.remove(tagToCategory);

                    /* and remove it from the tag collection */
                    final ArrayList<TopicToTag> removeTopicToTagList = new ArrayList<TopicToTag>();
                    for (final TopicToTag topicToTag : topic.getTopicToTags()) {
                        if (topicToTag.getTag().equals(removeTag)) removeTopicToTagList.add(topicToTag);
                    }

                    for (final TopicToTag removeTopicToTag : removeTopicToTagList) {
                        topic.getTopicToTags().remove(removeTopicToTag);
                    }
                }
            }

            /* remove tags that are explicitly defined as mutually exclusive */
            for (final TagToCategory tagToCategory : tagToCategories) {
                final Tag tag = tagToCategory.getTag();
                for (final Tag exclusionTag : tag.getExcludedTags()) {
                    if (filter(having(on(TopicToTag.class).getTag(), equalTo(tagToCategory.getTag())),
                            topic.getTopicToTags()).size() != 0 && // make
                            /*
                             * sure that we have not removed this tag already
                             */
                            filter(having(on(TopicToTag.class).getTag(), equalTo(exclusionTag)),
                                    topic.getTopicToTags()).size() != 0 && // make
                            /*
                             * sure the exclusion tag exists
                             */
                            !exclusionTag.equals(tagToCategory.getTag())) // make
                    /*
                     * sure we are not trying to remove ourselves
                     */ {
                        with(topic.getTopicToTags()).remove(having(on(TopicToTag.class).getTag(), equalTo(exclusionTag)));
                    }
                }
            }
        }
    }
Validate and Fix a topics tags so that mutually exclusive tags are enforced and also remove any tags that may have been
duplicated.

@param topic The topic to fix the tags for.