/* * #! * Ontopia Navigator * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.topicmaps.nav.context; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import net.ontopia.topicmaps.core.TopicIF; import net.ontopia.topicmaps.core.TopicMapIF; import net.ontopia.utils.StringUtils; import net.ontopia.utils.StringifierIF; import net.ontopia.utils.LexicalComparator; import net.ontopia.utils.GrabberStringifier; import net.ontopia.topicmaps.nav.utils.comparators.TopicComparator; import net.ontopia.topicmaps.nav.utils.comparators.ContextNameGrabber; import net.ontopia.topicmaps.utils.NameStringifier; import net.ontopia.topicmaps.utils.PSI; /** * INTERNAL: Class for categorizing a collection of themes according to * their theme class. The theme classes as well as the themes in each * theme class could be sorted. */ public class ThemeCategorizer { /** representation of theme class for themes which belong to no type */ protected static final String STRING_NO_CLASS = "[unspecified]"; /** Stringifier for theme class topics */ protected StringifierIF stringifier; /** for sorting the theme class strings */ protected Comparator lexicalComparator; /** for sorting the theme topics */ protected Comparator topicComparator; /** * empty constructor. */ public ThemeCategorizer(TopicMapIF tm, Collection context) { init(tm, context); } /** * INTERNAL: initialisation of Stringifier and Comparators */ private void init(TopicMapIF tm, Collection context) { TopicIF display = tm.getTopicBySubjectIdentifier(PSI.getXTMDisplay()); TopicIF sort = tm.getTopicBySubjectIdentifier(PSI.getXTMSort()); // ----- initialisation // for output of theme class topic basename Collection vnc = new ArrayList(context); if (display != null) vnc.add(display); stringifier = new GrabberStringifier(new ContextNameGrabber(context, vnc), new NameStringifier()); // for string sorting use case-insensitive Lexical Comparator lexicalComparator = LexicalComparator.CASE_SENSITIVE; // for topic sorting (themes) vnc = new ArrayList(context); if (sort != null) vnc.add(sort); topicComparator = new TopicComparator(context, vnc); } /** * INTERNAL: Returns the internal stringifier used to stringify * topics correctly in the current context. */ public StringifierIF getTopicStringifier() { return stringifier; } /** * process <code>themes</code> and generate HashMap which * reflects theme categories. * * @return HashMap which contains as keys Strings * of the theme type that lead to HasSet objects. * These store TopicIF objects for the themes. */ public HashMap getThemeClasses(Collection themes) { // list of theme classes HashMap themeClassMap = new HashMap(); themeClassMap.put(STRING_NO_CLASS, new HashSet()); Iterator itThemes = themes.iterator(); TopicIF actTheme = null; // ----- iterate through all base name themes while (itThemes.hasNext()) { actTheme = (TopicIF) itThemes.next(); // find out theme classes of this theme Collection themeTypes = actTheme.getTypes(); HashSet actSet; if (themeTypes.size() > 0) { Iterator itThemeTypes = themeTypes.iterator(); TopicIF actThemeType = null; String actThemeTypeString; while (itThemeTypes.hasNext()) { actThemeType = (TopicIF) itThemeTypes.next(); actThemeTypeString = stringifier.toString( actThemeType ); // if theme class already exists, just get the set, otherwise create it if (themeClassMap.containsKey(actThemeTypeString)) { actSet = (HashSet) themeClassMap.get(actThemeTypeString); } else { actSet = new HashSet(); themeClassMap.put(actThemeTypeString, actSet); } actSet.add(actTheme); } // while itThemeTypes } else { actSet = (HashSet) themeClassMap.get(STRING_NO_CLASS); actSet.add(actTheme); } } // while itThemes return themeClassMap; } /** * Generate a ordered list of theme classes. * Note: In every theme class there are at least one theme. */ public String generateThemeList(HashMap themeClassMap, StringifierIF stringifierThemeClass, StringifierIF stringifierTheme) { return generateThemeList(themeClassMap, null, stringifierThemeClass, stringifierTheme, null); } /** * Generate a ordered list of theme classes. * The themes which are found in the collection of selectedThemes use * their own stringifier <code>stringifierSelectedTheme</code>. * Note: In every theme class there are at least one theme. */ public String generateThemeList(HashMap themeClassMap, Collection selectedThemes, StringifierIF stringifierThemeClass, StringifierIF stringifierTheme, StringifierIF stringifierSelectedTheme) { if (themeClassMap == null || stringifierThemeClass == null || stringifierTheme == null) return ""; StringBuilder strBuf = new StringBuilder(); // ----- loop over all themes classes List themeClassList = new ArrayList( themeClassMap.keySet() ); Collections.sort( themeClassList, lexicalComparator ); Iterator itThemeClasses = themeClassList.iterator(); String actThemeClass; HashSet actSet; List themeList; Iterator itRelThemes; TopicIF actTheme; while (itThemeClasses.hasNext()) { actThemeClass = (String) itThemeClasses.next(); actSet = (HashSet) themeClassMap.get(actThemeClass); // only proceed if category name has related themes if (actSet.size() > 0) { // append string representation for theme class strBuf.append( stringifierThemeClass.toString( actThemeClass) ); // themeList = new ArrayList(stringifyTopics((Collection) actSet, stringifier)); themeList = new ArrayList( actSet ); Collections.sort( themeList, topicComparator ); itRelThemes = themeList.iterator(); while (itRelThemes.hasNext()) { actTheme = (TopicIF) itRelThemes.next(); // append string representation for theme if (selectedThemes != null && stringifierSelectedTheme != null) { if (selectedThemes.contains(actTheme)) strBuf.append( stringifierSelectedTheme.toString( actTheme )); else strBuf.append( stringifierTheme.toString( actTheme )); } else { strBuf.append( stringifierTheme.toString( actTheme )); } } // while itRelThemes } } // while itThemeClasses return strBuf.toString(); } /** * Generate a ordered list of theme classes. * Use template strings to render result string, this approach * is used by the navigator framework 2nd generation. * Note: In every theme class there are at least one theme. */ public String generateThemeList(HashMap themeClassMap, Collection selectedThemes, String templThemeClass, String templTheme, String templSelectedTheme) { if (themeClassMap == null || templThemeClass == null || templTheme == null) return ""; if (templSelectedTheme == null) templSelectedTheme = ""; StringBuilder strBuf = new StringBuilder(); // ----- loop over all themes classes List themeClassList = new ArrayList( themeClassMap.keySet() ); Collections.sort( themeClassList, lexicalComparator ); Iterator itThemeClasses = themeClassList.iterator(); String actThemeClass; HashSet actSet; List themeList; Iterator itRelThemes; TopicIF actTheme; String tmp; while (itThemeClasses.hasNext()) { actThemeClass = (String) itThemeClasses.next(); actSet = (HashSet) themeClassMap.get(actThemeClass); // only proceed if category name has related themes if (actSet.size() > 0) { // -- append string representation for theme class strBuf.append(StringUtils.replace(templThemeClass, "%className%", actThemeClass)); themeList = new ArrayList( actSet ); Collections.sort( themeList, topicComparator ); itRelThemes = themeList.iterator(); while (itRelThemes.hasNext()) { actTheme = (TopicIF) itRelThemes.next(); // a: replace theme name tmp = StringUtils.replace(templTheme, "%themeName%", stringifier.toString(actTheme)); // b: replace theme id tmp = StringUtils.replace(tmp, "%themeId%", actTheme.getObjectId()); // c: if selected, replace selected template if (selectedThemes != null && selectedThemes.contains(actTheme)) tmp = StringUtils.replace(tmp, "%selected%", templSelectedTheme); else tmp = StringUtils.replace(tmp, "%selected%", ""); // -- append string representation for theme strBuf.append( tmp ); } // while itRelThemes } } // while itThemeClasses return strBuf.toString(); } // // internal helper methods // /** * INTERNAL: generate new Collection of String objects out of * stringified TopicIF Collection. */ private static Collection stringifyTopics(Collection topics, StringifierIF stringifier) { Collection res = new ArrayList(); Iterator it = topics.iterator(); TopicIF actTopic; String actTopicString; while (it.hasNext()) { actTopic = (TopicIF) it.next(); actTopicString = stringifier.toString( actTopic ); res.add(actTopicString); } return res; } }