1 11 package org.eclipse.help.internal.index; 12 13 import java.util.Arrays ; 14 import java.util.Comparator ; 15 import java.util.HashMap ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import org.eclipse.help.ITopic; 23 import org.eclipse.help.IUAElement; 24 import org.eclipse.help.internal.HelpPlugin; 25 import org.eclipse.help.internal.Topic; 26 import org.eclipse.help.internal.UAElement; 27 import org.eclipse.help.internal.dynamic.DocumentProcessor; 28 import org.eclipse.help.internal.dynamic.DocumentReader; 29 import org.eclipse.help.internal.dynamic.ExtensionHandler; 30 import org.eclipse.help.internal.dynamic.IncludeHandler; 31 import org.eclipse.help.internal.dynamic.ProcessorHandler; 32 import org.eclipse.help.internal.toc.HrefUtil; 33 34 38 public class IndexAssembler { 39 40 private DocumentProcessor processor; 41 private Comparator comparator; 42 private String locale; 43 44 48 public Index assemble(List contributions, String locale) { 49 this.locale = locale; 50 process(contributions); 51 Index index = merge(contributions); 52 sort(index); 53 return index; 54 } 55 56 59 private Index merge(List contributions) { 60 Index index = new Index(); 61 Iterator iter = contributions.iterator(); 62 while (iter.hasNext()) { 63 IndexContribution contribution = (IndexContribution)iter.next(); 64 mergeChildren(index, (Index)contribution.getIndex()); 65 } 66 return index; 67 } 68 69 75 private void mergeChildren(UAElement a, UAElement b) { 76 Map entriesByKeyword = new HashMap (); 78 Set topicHrefs = new HashSet (); 79 IUAElement[] childrenA = a.getChildren(); 80 for (int i=0;i<childrenA.length;++i) { 81 UAElement childA = (UAElement)childrenA[i]; 82 if (childA instanceof IndexEntry) { 83 entriesByKeyword.put(childA.getAttribute(IndexEntry.ATTRIBUTE_KEYWORD), childA); 84 } 85 else if (childA instanceof Topic) { 86 topicHrefs.add(childA.getAttribute(Topic.ATTRIBUTE_HREF)); 87 } 88 } 89 90 IUAElement[] childrenB = b.getChildren(); 92 for (int i=0;i<childrenB.length;++i) { 93 UAElement childB = (UAElement)childrenB[i]; 94 if (childB instanceof IndexEntry) { 95 String keyword = childB.getAttribute(IndexEntry.ATTRIBUTE_KEYWORD); 96 if (entriesByKeyword.containsKey(keyword)) { 97 mergeChildren((IndexEntry)entriesByKeyword.get(keyword), childB); 99 } 100 else { 101 a.appendChild(childB); 103 entriesByKeyword.put(keyword, childB); 104 } 105 } 106 else if (childB instanceof Topic) { 107 String href = childB.getAttribute(Topic.ATTRIBUTE_HREF); 108 if (!topicHrefs.contains(href)) { 109 a.appendChild(childB); 111 topicHrefs.add(href); 112 } 113 } 114 } 115 } 116 117 private void process(List contributions) { 118 if (processor == null) { 119 DocumentReader reader = new DocumentReader(); 120 processor = new DocumentProcessor(new ProcessorHandler[] { 121 new NormalizeHandler(), 122 new IncludeHandler(reader, locale), 123 new ExtensionHandler(reader, locale), 124 }); 125 } 126 Iterator iter = contributions.iterator(); 127 while (iter.hasNext()) { 128 IndexContribution contribution = (IndexContribution)iter.next(); 129 processor.process((Index)contribution.getIndex(), contribution.getId()); 130 } 131 } 132 133 136 private void sort(UAElement element) { 137 if (comparator == null) { 138 comparator = new IndexComparator(); 139 } 140 sort(element, comparator); 141 } 142 143 147 private void sort(UAElement element, Comparator comparator) { 148 IUAElement[] children = element.getChildren(); 150 for (int i=0;i<children.length;++i) { 151 element.removeChild((UAElement)children[i]); 152 } 153 Arrays.sort(children, comparator); 154 for (int i=0;i<children.length;++i) { 155 element.appendChild((UAElement)children[i]); 156 } 157 for (int i=0;i<children.length;++i) { 159 sort((UAElement)children[i], comparator); 160 } 161 } 162 163 167 private class NormalizeHandler extends ProcessorHandler { 168 public short handle(UAElement element, String id) { 169 if (element instanceof Topic) { 170 Topic topic = (Topic)element; 171 String href = topic.getHref(); 172 if (href != null) { 173 int index = id.indexOf('/', 1); 174 if (index != -1) { 175 String pluginId = id.substring(1, index); 176 topic.setHref(HrefUtil.normalizeHref(pluginId, href)); 177 } 178 } 179 } 180 return UNHANDLED; 181 } 182 } 183 184 private static class IndexComparator implements Comparator { 185 public int compare(Object o1, Object o2) { 186 191 int c1 = getCategory((UAElement)o1); 192 int c2 = getCategory((UAElement)o2); 193 if (c1 == c2) { 194 String s1 = getLabel((UAElement)o1).toLowerCase(); 196 String s2 = getLabel((UAElement)o2).toLowerCase(); 197 return s1.compareTo(s2); 198 } 199 else { 200 return c1 - c2; 202 } 203 } 204 205 213 private static int getCategory(UAElement element) { 214 if (element instanceof Topic) { 215 return 0; 216 } 217 else if (element instanceof IndexEntry) { 218 String keyword = ((IndexEntry)element).getKeyword(); 219 if (keyword != null && keyword.length() > 0) { 220 char c = keyword.charAt(0); 221 if (Character.isDigit(c)) { 222 return 2; 223 } 224 else if (Character.isLetter(c)) { 225 return 3; 226 } 227 return 1; 228 } 229 return 4; 230 } 231 else { 232 return 5; 233 } 234 } 235 236 240 private static String getLabel(UAElement element) { 241 if (element instanceof Topic) { 242 Topic topic = (Topic)element; 243 if (topic.getLabel() == null) { 244 ITopic topic2 = HelpPlugin.getTocManager().getTopic(topic.getHref()); 245 if (topic2 != null) { 246 topic.setLabel(topic2.getLabel()); 247 } 248 else { 249 String msg = "Unable to look up label for help keyword index topic \"" + topic.getHref() + "\" with missing \"" + Topic.ATTRIBUTE_LABEL + "\" attribute (topic does not exist in table of contents; using href as label)"; HelpPlugin.logError(msg); 251 topic.setLabel(topic.getHref()); 252 } 253 } 254 return topic.getLabel(); 255 } 256 else if (element instanceof IndexEntry) { 257 return ((IndexEntry)element).getKeyword(); 258 } 259 return null; 260 } 261 }; 262 } 263 | Popular Tags |