1 /******************************************************************************* 2 * Copyright (c) 2010, 2015 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 15 package org.eclipse.help.internal.base.scope; 16 17 import java.util.ArrayList; 18 import java.util.List; 19 20 import org.eclipse.help.IIndexEntry; 21 import org.eclipse.help.IIndexEntry2; 22 import org.eclipse.help.IIndexSee; 23 import org.eclipse.help.IToc; 24 import org.eclipse.help.ITopic; 25 import org.eclipse.help.IUAElement; 26 import org.eclipse.help.base.AbstractHelpScope; 27 import org.eclipse.help.internal.UAElement; 28 import org.eclipse.help.internal.index.Index; 29 import org.eclipse.help.internal.index.IndexSee; 30 31 /** 32 * Utilities to test for enabled topics, index entries etc. 33 */ 34 35 public class ScopeUtils { 36 37 38 /* 39 * Function to determine whether a topic should be shown in the toc. 40 * For hierarchical scopes the element itself must be in scope. 41 * For non hierarchical scopes if any child is in scope the element should show. 42 * A toc with no in scope topics does not display 43 */ showInTree(IToc toc, AbstractHelpScope scope)44 public static boolean showInTree(IToc toc, AbstractHelpScope scope) { 45 if (scope.isHierarchicalScope() && !scope.inScope(toc)) { 46 return false; 47 } 48 return hasInScopeDescendent(toc, scope); 49 50 } 51 52 /* 53 * Function to determine whether a topic should be shown in the toc. 54 * For hierarchical scopes the element itself must be in scope. 55 * For non hierarchical scopes if any child is in scope the element should show. 56 * Leaf topics with no href do not show in the toc 57 */ showInTree(ITopic topic, AbstractHelpScope scope)58 public static boolean showInTree(ITopic topic, AbstractHelpScope scope) { 59 if (scope.inScope(topic)) { 60 return (topic.getHref() != null) || hasInScopeDescendent(topic, scope); 61 } 62 return !scope.isHierarchicalScope() && hasInScopeDescendent(topic, scope); 63 } 64 65 /* 66 * Function to determine whether an entry should be shown in the index. 67 * For hierarchical scopes the element itself must be in scope. 68 * For non hierarchical scopes if any child is in scope the element should show. 69 * An entry with no topic descendants does not display 70 */ showInTree(IIndexEntry entry, AbstractHelpScope scope)71 public static boolean showInTree(IIndexEntry entry, AbstractHelpScope scope) { 72 if (scope.isHierarchicalScope() && !scope.inScope(entry)) { 73 return false; 74 } 75 return hasInScopeDescendent(entry, scope); 76 } 77 78 /* 79 * Returns true if one of the children meets the conditions 80 * necessary to be shown in the Toc tree 81 */ hasInScopeDescendent(ITopic topic, AbstractHelpScope scope)82 public static boolean hasInScopeDescendent(ITopic topic, AbstractHelpScope scope) { 83 ITopic[] subtopics = topic.getSubtopics(); 84 for (ITopic subtopic : subtopics) { 85 if (showInTree(subtopic, scope)) { 86 return true; 87 } 88 } 89 return false; 90 } 91 92 /* 93 * Returns true if one of the children meets the conditions 94 * necessary to be shown in the Toc tree 95 */ hasInScopeDescendent(IToc toc, AbstractHelpScope scope)96 public static boolean hasInScopeDescendent(IToc toc, AbstractHelpScope scope) { 97 ITopic[] topics = toc.getTopics(); 98 for (ITopic topic : topics) { 99 if (showInTree(topic, scope)) { 100 return true; 101 } 102 } 103 return false; 104 } 105 106 /* 107 * Returns true if one of the children meets the conditions 108 * necessary to be shown in the Index 109 */ hasInScopeDescendent(IIndexEntry entry, AbstractHelpScope scope)110 public static boolean hasInScopeDescendent(IIndexEntry entry, 111 AbstractHelpScope scope) { 112 ITopic[] topics = entry.getTopics(); 113 for (ITopic topic : topics) { 114 if (showInTree(topic, scope)) { 115 return true; 116 } 117 } 118 IIndexEntry[] entries = entry.getSubentries(); 119 for (IIndexEntry innerEntry : entries) { 120 if (showInTree(innerEntry, scope)) { 121 return true; 122 } 123 } 124 if (entry instanceof IIndexEntry2) { 125 IIndexSee[] sees = ((IIndexEntry2)entry).getSees(); 126 for (IIndexSee see : sees) { 127 if (showInTree(see, scope)) { 128 return true; 129 } 130 } 131 } 132 return false; 133 } 134 hasInScopeTarget(IIndexSee see, AbstractHelpScope scope)135 public static boolean hasInScopeTarget(IIndexSee see, AbstractHelpScope scope) { 136 if (see instanceof IndexSee) { 137 IndexSee indexSee = (IndexSee)see; 138 UAElement ancestor = indexSee.getParentElement(); 139 while (!(ancestor instanceof Index)) { 140 if (ancestor == null) { 141 return true; 142 } 143 ancestor = ancestor.getParentElement(); 144 } 145 IIndexEntry target = ((Index)ancestor).getSeeTarget(indexSee); 146 if (target == null) { 147 return false; 148 } 149 return showInTree(target, scope); 150 } 151 return false; 152 } 153 showInTree(IIndexSee see, AbstractHelpScope scope)154 public static boolean showInTree(IIndexSee see, AbstractHelpScope scope) { 155 if (scope.isHierarchicalScope() && !scope.inScope(see)) { 156 return false; 157 } 158 if (see instanceof IndexSee) { 159 IndexSee indexSee = (IndexSee)see; 160 UAElement ancestor = indexSee.getParentElement(); 161 while (!(ancestor instanceof Index)) { 162 if (ancestor == null) { 163 return true; 164 } 165 ancestor = ancestor.getParentElement(); 166 } 167 IIndexEntry target = ((Index)ancestor).getSeeTarget(indexSee); 168 if (target == null) { 169 return false; 170 } 171 return showInTree(target, scope); 172 } 173 return false; 174 } 175 176 /** 177 * Filter out any disabled entries from an array 178 * @param entries an array of entries 179 * @param scope 180 * @return an array containing only those entries which are enabled 181 */ inScopeEntries(IIndexEntry[] entries, AbstractHelpScope scope)182 public static IIndexEntry[] inScopeEntries(IIndexEntry[] entries, AbstractHelpScope scope) { 183 for (int i=0;i<entries.length;++i) { 184 if (!scope.inScope(entries[i])) { 185 List<IIndexEntry> list = new ArrayList<>(entries.length); 186 for (int j=0;j<entries.length;++j) { 187 if (j < i || scope.inScope(entries[j])) { 188 list.add(entries[j]); 189 } 190 } 191 return list.toArray(new IIndexEntry[list.size()]); 192 } 193 } 194 return entries; 195 } 196 197 /** 198 * Filter out any disabled topics from an array 199 * @param topics an array of topics 200 * @param scope 201 * @return an array containing only those topics which are enabled 202 */ inScopeTopics(ITopic[] topics, AbstractHelpScope scope)203 public static ITopic[] inScopeTopics(ITopic[] topics, AbstractHelpScope scope) { 204 for (int i=0;i<topics.length;++i) { 205 if (!scope.inScope(topics[i])) { 206 List<ITopic> list = new ArrayList<>(topics.length); 207 for (int j=0;j<topics.length;++j) { 208 if (j < i || scope.inScope(topics[j])) { 209 list.add(topics[j]); 210 } 211 } 212 return list.toArray(new ITopic[list.size()]); 213 } 214 } 215 return topics; 216 } 217 hasInScopeChildren(IUAElement element, AbstractHelpScope scope)218 public static boolean hasInScopeChildren(IUAElement element, 219 AbstractHelpScope scope) { 220 if (element instanceof IToc) { 221 return hasInScopeDescendent((IToc)element, scope); 222 } 223 if (element instanceof ITopic) { 224 return hasInScopeDescendent((ITopic)element, scope); 225 } 226 if (element instanceof IIndexEntry) { 227 return hasInScopeDescendent((IIndexEntry) element, scope); 228 } 229 if (element instanceof IIndexSee) { 230 return hasInScopeTarget((IIndexSee) element, scope); 231 } 232 return false; 233 } 234 235 } 236