| /******************************************************************************* |
| * Copyright (c) 2004, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.core.internal.registry; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.InvalidRegistryObjectException; |
| |
| // This object is used to keep track on a contributor basis of the extension and extension points being contributed. |
| // It is mainly used on removal so we can quickly find objects to remove. |
| // Each contribution is made in the context of a namespace. |
| public class Contribution implements KeyedElement { |
| static final int[] EMPTY_CHILDREN = new int[] {0, 0}; |
| |
| //The registry that owns this object |
| protected ExtensionRegistry registry; |
| |
| // The actual contributor of the contribution |
| final protected String contributorId; |
| |
| // Value is derived from the contributorId and cached for performance |
| private String defaultNamespace = null; |
| |
| // indicates if this contribution needs to be saved in the registry cache |
| protected boolean persist; |
| |
| // This array stores the identifiers of both the extension points and the extensions. |
| // The array has always a minimum size of 2. |
| // The first element of the array is the number of extension points and the second the number of extensions. |
| // [numberOfExtensionPoints, numberOfExtensions, extensionPoint#1, extensionPoint#2, extensionPoint..., ext#1, ext#2, ext#3, ... ]. |
| // The size of the array is 2 + (numberOfExtensionPoints + numberOfExtensions). |
| private int[] children = EMPTY_CHILDREN; |
| static final public byte EXTENSION_POINT = 0; |
| static final public byte EXTENSION = 1; |
| |
| protected Contribution(String contributorId, ExtensionRegistry registry, boolean persist) { |
| this.contributorId = contributorId; |
| this.registry = registry; |
| this.persist = persist; |
| } |
| |
| void mergeContribution(Contribution addContribution) { |
| Assert.isTrue(contributorId.equals(addContribution.contributorId)); |
| Assert.isTrue(registry == addContribution.registry); |
| |
| // persist? |
| // Old New Result |
| // F F F |
| // F T T => needs to be adjusted |
| // T F T |
| // T T T |
| if (shouldPersist() != addContribution.shouldPersist()) |
| persist = true; |
| |
| int[] existing = getRawChildren(); |
| int[] addition = addContribution.getRawChildren(); |
| |
| int extensionPoints = existing[EXTENSION_POINT] + addition[EXTENSION_POINT]; |
| int extensions = existing[EXTENSION] + addition[EXTENSION]; |
| int[] allChildren = new int[2 + extensionPoints + extensions]; |
| |
| allChildren[EXTENSION_POINT] = extensionPoints; |
| System.arraycopy(existing, 2, allChildren, 2, existing[EXTENSION_POINT]); |
| System.arraycopy(addition, 2, allChildren, 2 + existing[EXTENSION_POINT], addition[EXTENSION_POINT]); |
| allChildren[EXTENSION] = extensions; |
| System.arraycopy(existing, 2 + existing[EXTENSION_POINT], allChildren, 2 + extensionPoints, existing[EXTENSION]); |
| System.arraycopy(addition, 2 + addition[EXTENSION_POINT], allChildren, 2 + extensionPoints + existing[EXTENSION], addition[EXTENSION]); |
| |
| children = allChildren; |
| } |
| |
| void setRawChildren(int[] children) { |
| this.children = children; |
| } |
| |
| protected String getContributorId() { |
| return contributorId; |
| } |
| |
| protected int[] getRawChildren() { |
| return children; |
| } |
| |
| protected int[] getExtensions() { |
| int[] results = new int[children[EXTENSION]]; |
| System.arraycopy(children, 2 + children[EXTENSION_POINT], results, 0, children[EXTENSION]); |
| return results; |
| } |
| |
| protected int[] getExtensionPoints() { |
| int[] results = new int[children[EXTENSION_POINT]]; |
| System.arraycopy(children, 2, results, 0, children[EXTENSION_POINT]); |
| return results; |
| } |
| |
| public String getDefaultNamespace() { |
| if (defaultNamespace == null) |
| defaultNamespace = registry.getObjectManager().getContributor(contributorId).getName(); |
| return defaultNamespace; |
| } |
| |
| @Override |
| public String toString() { |
| return "Contribution: " + contributorId + " in namespace" + getDefaultNamespace(); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| //Implements the KeyedElement interface |
| @Override |
| public int getKeyHashCode() { |
| return getKey().hashCode(); |
| } |
| |
| @Override |
| public Object getKey() { |
| return contributorId; |
| } |
| |
| @Override |
| public boolean compare(KeyedElement other) { |
| return contributorId.equals(((Contribution) other).contributorId); |
| } |
| |
| public boolean shouldPersist() { |
| return persist; |
| } |
| |
| public void unlinkChild(int id) { |
| // find index of the child being unlinked: |
| int index = -1; |
| for (int i = 2; i < children.length; i++) { |
| if (children[i] == id) { |
| index = i; |
| break; |
| } |
| } |
| if (index == -1) |
| throw new InvalidRegistryObjectException(); |
| |
| // copy all array except one element at index |
| int[] result = new int[children.length - 1]; |
| System.arraycopy(children, 0, result, 0, index); |
| System.arraycopy(children, index + 1, result, index, children.length - index - 1); |
| |
| // fix sizes |
| if (index < children[EXTENSION_POINT] + 2) |
| result[EXTENSION_POINT]--; |
| else |
| result[EXTENSION]--; |
| |
| children = result; |
| } |
| |
| /** |
| * Contribution is empty if it has no children. |
| */ |
| public boolean isEmpty() { |
| return (children[EXTENSION_POINT] == 0 || children[EXTENSION] == 0); |
| } |
| |
| /** |
| * Find if this contribution has a children with ID = id. |
| * @param id possible ID of the child |
| * @return true: contribution has this child |
| */ |
| public boolean hasChild(int id) { |
| for (int i = 2; i < children.length; i++) { |
| if (children[i] == id) |
| return true; |
| } |
| return false; |
| } |
| } |