/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.ui.internal.branch; import static org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants.TAG_ENABLEMENT; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.expressions.EvaluationContext; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.Platform; import org.eclipse.ui.internal.registry.RegistryReader; import org.xmind.ui.branch.IBranchPolicy; import org.xmind.ui.branch.IBranchPolicyCategoryDescriptor; import org.xmind.ui.branch.IBranchPolicyDescriptor; import org.xmind.ui.branch.IBranchPolicyManager; import org.xmind.ui.branch.IBranchPropertyTester; import org.xmind.ui.branch.IBranchStyleValueProvider; import org.xmind.ui.internal.RegistryConstants; import org.xmind.ui.mindmap.IBranchPart; import org.xmind.ui.mindmap.MindMapUI; import org.xmind.ui.util.Logger; /** * This class is not intended to be instantiate by clients. Call * {@link org.xmind.ui.mindmap.MindMapUI#getBranchPolicyManager()} to obtain an * instance of this class. * * @author MANGOSOFT */ public class BranchPolicyManager extends RegistryReader implements IBranchPolicyManager { private static final String V_CALLOUT_BRANCHES = "calloutBranches"; //$NON-NLS-1$ private static final String DEFAULT_BRANCH_POLICY_ID = "org.xmind.ui.map.unbalanced"; //$NON-NLS-1$ private static final String V_PARENT_BRANCH = "parentBranch"; //$NON-NLS-1$ private static final String V_SUB_BRANCHES = "subBranches"; //$NON-NLS-1$ private static final String V_SUMMARY_BRANCHES = "summaryBranches"; //$NON-NLS-1$ private static final String V_BOUNDARIES = "boundaries"; //$NON-NLS-1$ private static final String V_SUMMARIES = "summaries"; //$NON-NLS-1$ private static final String V_TOPIC = "topic"; //$NON-NLS-1$ static IEvaluationContext createBranchEvaluationContext(IBranchPart branch) { EvaluationContext context = new EvaluationContext(null, branch); IBranchPart parentBranch = branch.getParentBranch(); context.addVariable(V_PARENT_BRANCH, parentBranch == null ? IEvaluationContext.UNDEFINED_VARIABLE : parentBranch); context.addVariable(V_SUB_BRANCHES, branch.getSubBranches()); context.addVariable(V_CALLOUT_BRANCHES, branch.getCalloutBranches()); context.addVariable(V_SUMMARY_BRANCHES, branch.getSummaryBranches()); context.addVariable(V_BOUNDARIES, branch.getBoundaries()); context.addVariable(V_SUMMARIES, branch.getSummaries()); context.addVariable(V_TOPIC, branch.getTopic()); return context; } private List<IBranchPolicyDescriptor> policyList = null; private Map<String, BranchPolicy> policyMap = null; private Map<String, StructureDescriptor> structureMap = null; private Map<String, BranchPropertyTesterProxy> testerMap = null; private Map<String, ContributedStyleValueProvider> valueProviderMap = null; private IBranchPolicy defaultBranchPolicy = null; private List<IBranchPolicyCategoryDescriptor> categoryList = null; private Map<String, BranchPolicyCategoryDescriptor> categoryMap = null; /** * This class is not intended to be instantiate by clients. */ public BranchPolicyManager() { } /* * (non-Javadoc) * * @see org.xmind.ui.internal.IBranchPolicyRegistry#getDescriptors() */ public List<IBranchPolicyDescriptor> getBranchPolicyDescriptors() { ensureLoaded(); return policyList; } public List<IBranchPolicyCategoryDescriptor> getBranchPolicyCategoryDescriptors() { ensureLoaded(); return categoryList; } private Map<String, BranchPolicy> getPolicyMap() { ensureLoaded(); return policyMap; } private Map<String, StructureDescriptor> getStructureMap() { ensureLoaded(); return structureMap; } private Map<String, BranchPolicyCategoryDescriptor> getCategoryMap() { ensureLoaded(); return categoryMap; } public IStructureDescriptor getStructureDescriptor(String id) { if (id != null) { StructureDescriptor structure = getStructureMap().get(id); if (structure != null) return structure; } return DefaultStructureDescriptor.getInstance(); } public IBranchPropertyTester getPropertyTester(String id) { ensureLoaded(); return testerMap.get(id); } public IBranchStyleValueProvider getValueProvider(String id) { ensureLoaded(); return valueProviderMap.get(id); } private BranchPolicy getPolicy(String id) { return getPolicyMap().get(id); } public IBranchPolicyCategoryDescriptor getBranchPolicyCategoryDescriptor( String categoryId) { if (categoryId != null) { return getCategoryMap().get(categoryId); } return null; } /* * (non-Javadoc) * * @see org.xmind.ui.internal.IBranchPolicyRegistry#getDescriptor(java * .lang.String) */ public IBranchPolicyDescriptor getBranchPolicyDescriptor(String id) { return getPolicy(id); } public IBranchPolicy getBranchPolicy(String id) { BranchPolicy policy = getPolicy(id); if (policy == null) { policy = getPolicy(DEFAULT_BRANCH_POLICY_ID); if (policy == null) return getDefaultBranchPolicy(); } return policy; } public IBranchPolicy getDefaultBranchPolicy() { if (defaultBranchPolicy == null) { defaultBranchPolicy = new DefaultBranchPolicy(this); } return defaultBranchPolicy; } public String calculateBranchPolicyId(IBranchPart branch, String prefferedPolicyId) { IBranchPart parent = branch.getParentBranch(); if (parent != null) { String parentId = parent.getBranchPolicyId(); BranchPolicy parentPolicy = getPolicy(parentId); if (parentPolicy != null && parentPolicy .canOverride(createBranchEvaluationContext(branch))) return parentId; } if (prefferedPolicyId != null) { BranchPolicy policy = getPolicy(prefferedPolicyId); if (policy != null && policy.isApplicableTo(branch)) return prefferedPolicyId; } if (parent != null && parent.getSubBranches().contains(branch)) return parent.getBranchPolicyId(); if (parent != null && parent.getCalloutBranches().contains(branch)) return parent.getBranchPolicyId(); return DEFAULT_BRANCH_POLICY_ID; } public List<IBranchPolicyDescriptor> getApplicableBranchPolicyDescriptors( IBranchPart branch) { if (branch == null) return Collections.emptyList(); ArrayList<IBranchPolicyDescriptor> list = new ArrayList<IBranchPolicyDescriptor>( getBranchPolicyDescriptors()); IEvaluationContext context = createBranchEvaluationContext(branch); for (Iterator<IBranchPolicyDescriptor> it = list.iterator(); it .hasNext();) { if (!((BranchPolicy) it.next()).isApplicableTo(context)) { it.remove(); } } return list; } private void ensureLoaded() { if (policyMap == null || policyList == null || structureMap == null || testerMap == null || valueProviderMap == null || categoryList == null || categoryMap == null) lazyLoad(); if (policyList == null) policyList = Collections.emptyList(); if (policyMap == null) policyMap = Collections.emptyMap(); if (structureMap == null) structureMap = Collections.emptyMap(); if (testerMap == null) testerMap = Collections.emptyMap(); if (valueProviderMap == null) valueProviderMap = Collections.emptyMap(); if (categoryList == null) categoryList = Collections.emptyList(); if (categoryMap == null) categoryMap = Collections.emptyMap(); } private void lazyLoad() { if (Platform.isRunning()) { readRegistry(Platform.getExtensionRegistry(), MindMapUI.PLUGIN_ID, RegistryConstants.EXT_BRANCH_POLICIES); } } protected boolean readElement(IConfigurationElement element) { String name = element.getName(); if (RegistryConstants.TAG_BRANCH_POLICY.equals(name)) { readBranchPolicy(element); readElementChildren(element); return true; } else if (RegistryConstants.TAG_STRUCTURE.equals(name)) { readStructureAlgorithm(element); readElementChildren(element); return true; } else if (RegistryConstants.TAG_PROPERTY_TESTER.equals(name)) { readPropertyTester(element); readElementChildren(element); return true; } else if (RegistryConstants.TAG_STYLE_VALUE_PROVIDER.equals(name)) { readStyleValueProvider(element); readElementChildren(element); return true; } else if (RegistryConstants.TAG_ADDITIONAL_STRUCTURES.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_ADDITIONAL_STRUCTURE.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_BRANCH_HOOK.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_STYLE_SELECTOR.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_OVERRIDED_STYLE.equals(name)) { readElementChildren(element); return true; // } else if (RegistryConstants.TAG_INHERITED_STYLE.equals(name)) { // readElementChildren(element); // return true; } else if (RegistryConstants.TAG_UNMODIFIABLE_PROPERTIES.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_UNMODIFIABLE_PROPERTY.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_LAYER.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_STRUCTURE_CACHES.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_STRUCTURE_CACHE.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_OVERRIDE.equals(name)) { readElementChildren(element); return true; } else if (RegistryConstants.TAG_ADVISOR.equals(name)) { readElementChildren(element); return true; } else if (TAG_ENABLEMENT.equals(name)) { return true; } else if (RegistryConstants.TAG_BRANCH_POLICY_CATEGORY.equals(name)) { readBranchPolicyCategory(element); readElementChildren(element); return true; } return false; } private void readBranchPolicy(IConfigurationElement element) { try { BranchPolicy descriptor = new BranchPolicy(this, element); registerBranchPolicy(descriptor); } catch (CoreException e) { Logger.log(e, "Failed to load branch policy: " //$NON-NLS-1$ + element.toString()); } } private void readStructureAlgorithm(IConfigurationElement element) { try { StructureDescriptor descriptor = new StructureDescriptor(element); registryStructureAlgorithm(descriptor); } catch (CoreException e) { Logger.log(e, "Failed to load structure algorithm: " //$NON-NLS-1$ + element.toString()); } } private void readPropertyTester(IConfigurationElement element) { try { BranchPropertyTesterProxy proxy = new BranchPropertyTesterProxy( element); registerPropertyTester(proxy); } catch (CoreException e) { Logger.log(e, "Failed to load branch property tester: " //$NON-NLS-1$ + element.toString()); } } private void readStyleValueProvider(IConfigurationElement element) { try { ContributedStyleValueProvider valueProvider = new ContributedStyleValueProvider( element); registerValueProvider(valueProvider); } catch (CoreException e) { Logger.log(e, "Failed to load style value provider: " //$NON-NLS-1$ + element.toString()); } } private void readBranchPolicyCategory(IConfigurationElement element) { try { BranchPolicyCategoryDescriptor descriptor = new BranchPolicyCategoryDescriptor( element); registerBranchPolicyCategory(descriptor); } catch (CoreException e) { Logger.log(e, "Failed to load branch policy category: " //$NON-NLS-1$ + element.toString()); } } private void registerBranchPolicy(BranchPolicy descriptor) { if (policyList == null) policyList = new ArrayList<IBranchPolicyDescriptor>(); policyList.add(descriptor); if (policyMap == null) policyMap = new HashMap<String, BranchPolicy>(); policyMap.put(descriptor.getId(), descriptor); } private void registryStructureAlgorithm(StructureDescriptor descriptor) { if (structureMap == null) structureMap = new HashMap<String, StructureDescriptor>(); structureMap.put(descriptor.getId(), descriptor); } private void registerPropertyTester(BranchPropertyTesterProxy tester) { if (testerMap == null) testerMap = new HashMap<String, BranchPropertyTesterProxy>(); testerMap.put(tester.getId(), tester); } private void registerValueProvider( ContributedStyleValueProvider valueProvider) { if (valueProviderMap == null) valueProviderMap = new HashMap<String, ContributedStyleValueProvider>(); valueProviderMap.put(valueProvider.getId(), valueProvider); } private void registerBranchPolicyCategory( BranchPolicyCategoryDescriptor descriptor) { if (categoryList == null) categoryList = new ArrayList<IBranchPolicyCategoryDescriptor>(); categoryList.add(descriptor); if (categoryMap == null) categoryMap = new HashMap<String, BranchPolicyCategoryDescriptor>(); categoryMap.put(descriptor.getId(), descriptor); } /** * Start the registry reading process using the supplied plugin ID and * extension point. * * @param registry * the registry to read from * @param pluginId * the plugin id of the extenion point * @param extensionPoint * the extension point id */ public void readRegistry(IExtensionRegistry registry, String pluginId, String extensionPoint) { IExtensionPoint point = registry.getExtensionPoint(pluginId, extensionPoint); if (point == null) { return; } IExtension[] extensions = point.getExtensions(); if (extensions.length <= 0) return; // Comparator<IExtension> comparer = new Comparator<IExtension>() { // public int compare(IExtension arg0, IExtension arg1) { // String s1 = arg0.getNamespaceIdentifier(); // String s2 = arg1.getNamespaceIdentifier(); // return s1.compareToIgnoreCase(s2); // } // }; // IExtension myExtension = null; int i = 0; // for (; i < extensions.length; i++) { // IExtension ext = extensions[i]; // String contributorName = ext.getNamespaceIdentifier(); // if (contributorName.startsWith("org.xmind.")) { //$NON-NLS-1$ // myExtension = ext; // break; // } // } // if (myExtension != null) { // extensions[i] = extensions[0]; // extensions[0] = myExtension; // Arrays.sort(extensions, 1, extensions.length, comparer); // } else { // Arrays.sort(extensions, comparer); // } for (i = 0; i < extensions.length; i++) { readExtension(extensions[i]); } } }