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)));
                    }
                }
            }
        }
    }
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.
Validate and Fix a topics tags so that mutually exclusive tags are enforced and also remove any tags that may have been duplicated .