com.mansfield.pde.api.tools.internal.ui.preferencepages.TargetBaselinePreferencePage.java Source code

Java tutorial

Introduction

Here is the source code for com.mansfield.pde.api.tools.internal.ui.preferencepages.TargetBaselinePreferencePage.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Joseph Carroll 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:
 *     Joseph Carroll <jdsalingerjr@gmail.com> - initial API and implementation
 ******************************************************************************/
package com.mansfield.pde.api.tools.internal.ui.preferencepages;

import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.api.tools.internal.model.ApiModelFactory;
import org.eclipse.pde.api.tools.internal.model.Messages;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.IApiBaselineManager;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement;
import org.eclipse.pde.api.tools.internal.search.SkippedComponent;
import org.eclipse.pde.api.tools.internal.util.Util;
import org.eclipse.pde.api.tools.ui.internal.ApiToolsLabelProvider;
import org.eclipse.pde.api.tools.ui.internal.ApiUIPlugin;
import org.eclipse.pde.api.tools.ui.internal.preferences.ApiBaselinesConfigurationBlock;
import org.eclipse.pde.api.tools.ui.internal.preferences.PreferenceMessages;
import org.eclipse.pde.api.tools.ui.internal.wizards.ApiBaselineWizard;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetHandle;
import org.eclipse.pde.core.target.ITargetLocation;
import org.eclipse.pde.core.target.ITargetPlatformService;
import org.eclipse.pde.core.target.TargetBundle;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.PDEPreferencesManager;
import org.eclipse.pde.internal.core.PluginModelManager;
import org.eclipse.pde.internal.core.target.ExternalFileTargetHandle;
import org.eclipse.pde.internal.core.target.LocalTargetHandle;
import org.eclipse.pde.internal.core.target.TargetDefinition;
import org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle;
import org.eclipse.pde.internal.ui.IHelpContextIds;
import org.eclipse.pde.internal.ui.IPDEUIConstants;
import org.eclipse.pde.internal.ui.IPreferenceConstants;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEPluginImages;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.pde.internal.ui.shared.target.StyledBundleLabelProvider;
import org.eclipse.pde.internal.ui.util.SWTUtil;
import org.eclipse.pde.internal.ui.wizards.target.EditTargetDefinitionWizard;
import org.eclipse.pde.internal.ui.wizards.target.MoveTargetDefinitionWizard;
import org.eclipse.pde.internal.ui.wizards.target.NewTargetDefinitionWizard2;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;

import com.mansfield.pde.api.tools.internal.ui.SWTFactory;

@SuppressWarnings("restriction")
public class TargetBaselinePreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

    private static final String TARGET_BASELINE_EXTENSION = "@target"; //$NON-NLS-1$

    /**
     * Constant key value used to store data in table items if they are moved to a new location
     */
    private final static String DATA_KEY_MOVED_LOCATION = "movedLocation"; //$NON-NLS-1$

    private static final int NULL_DEFINITION = -1;

    // This is a candidate to be added to the ApiModelFactory
    private static IApiComponent[] addComponents(IApiBaseline baseline, ITargetDefinition targetDefinition,
            IProgressMonitor monitor) throws CoreException {
        SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.configuring_baseline, 50);
        IApiComponent[] result = null;
        try {
            // Acquire the service
            ITargetPlatformService service = (ITargetPlatformService) ApiPlugin.getDefault()
                    .acquireService(ITargetPlatformService.class.getName());
            IApiBaselineManager manager = ApiPlugin.getDefault().getApiBaselineManager();

            // Since this method is specific to Target's and the target would have to resolve,
            // if OSGi is not running then the environment is not in a valid state and we cannot 
            // proceed.
            if (service == null || manager == null) {
                return null;
            }

            Util.updateMonitor(subMonitor, 1);
            subMonitor.subTask(Messages.resolving_target_definition);

            ITargetLocation[] containers = targetDefinition.getTargetLocations();
            if (containers == null) {
                return null;
            }

            subMonitor.setWorkRemaining(30 * containers.length);
            List<TargetBundle> targetBundles = new ArrayList<TargetBundle>(79);
            for (int i = 0; i < containers.length; i++) {
                containers[i].resolve(targetDefinition, subMonitor.newChild(15));
                targetBundles.addAll(Arrays.asList(containers[i].getBundles()));
            }

            List<IApiComponent> components = new ArrayList<IApiComponent>(targetBundles.size());
            if (targetBundles.size() > 0) {
                subMonitor.setWorkRemaining(targetBundles.size());
                for (int i = 0; i < targetBundles.size(); i++) {
                    Util.updateMonitor(subMonitor, 1);
                    TargetBundle bundle = targetBundles.get(i);
                    if (!bundle.isSourceBundle()) {
                        IApiComponent component = ApiModelFactory.newApiComponent(baseline,
                                URIUtil.toFile(bundle.getBundleInfo().getLocation()).getAbsolutePath());
                        if (component != null) {
                            subMonitor.subTask(NLS.bind(Messages.adding_component__0, component.getSymbolicName()));
                            components.add(component);
                        }
                    }
                }
            }

            IApiBaseline existing = manager.getApiBaseline(baseline.getName());
            if (existing != null) {
                manager.removeApiBaseline(existing.getName());
            }
            manager.addApiBaseline(baseline);

            result = components.toArray(new IApiComponent[components.size()]);
            if (result != null) {
                baseline.addApiComponents(result);
                return result;
            }

            return new IApiComponent[0];
        } finally {
            subMonitor.done();
        }
    }

    // This is a candidate to be added to the Util
    public static final Comparator<IApiElement> componentSorter = new Comparator<IApiElement>() {
        public int compare(IApiElement o1, IApiElement o2) {
            if (o1 instanceof IApiComponent && o2 instanceof IApiComponent) {
                int eql = ((IApiComponent) o1).getSymbolicName().compareTo(((IApiComponent) o2).getSymbolicName());
                if (eql != 0) {
                    return eql;
                }

                return ((IApiComponent) o1).getVersion().compareTo(((IApiComponent) o2).getVersion());
            }
            if (o1 instanceof SkippedComponent && o2 instanceof SkippedComponent) {
                int eql = ((SkippedComponent) o1).getComponentId()
                        .compareTo(((SkippedComponent) o2).getComponentId());
                if (eql != 0) {
                    return eql;
                }

                return ((SkippedComponent) o1).getVersion().compareTo(((SkippedComponent) o2).getVersion());
            }
            return -1;
        }
    };

    // This is a candidate to be added to the Util
    private static boolean areEqual(IApiComponent comp1, IApiComponent comp2) {
        if (comp1 == null) {
            return comp2 == null;
        }
        if (comp2 == null) {
            return false;
        }

        if (comp1.getClass() != comp2.getClass()) {
            return false;
        }

        boolean isEqual = Util.equalsOrNull(comp1.getName(), comp2.getName());
        isEqual |= Util.equalsOrNull(comp1.getSymbolicName(), comp2.getSymbolicName());
        isEqual |= Util.equalsOrNull(comp1.getVersion(), comp2.getVersion());
        if (!isEqual) {
            return false;
        }

        if (comp1.getType() != comp2.getType()) {
            return false;
        }

        String[] envs1;
        String[] envs2;
        try {
            envs1 = comp1.getExecutionEnvironments();
            envs2 = comp2.getExecutionEnvironments();
        } catch (CoreException e) {
            return false;
        }

        if (envs1.length != envs2.length) {
            // CODE_REVIEW
            // ... Is this true?
            return false;
        }

        for (int i = 0; i < envs1.length && isEqual; i++) {
            isEqual &= envs1[i].equals(envs2[i]);
        }

        if (!isEqual) {
            return false;
        }

        return true;
    }

    private class DefinitionLocationLabelProvider extends StyledBundleLabelProvider {

        ApiToolsLabelProvider apiToolsProvider;

        public DefinitionLocationLabelProvider(boolean showVersion, boolean appendResolvedVariables) {
            super(showVersion, appendResolvedVariables);

            apiToolsProvider = new ApiToolsLabelProvider() {
                protected boolean isDefaultBaseline(Object element) {
                    return isDefault(element);
                }
            };
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.StyledCellLabelProvider#update(org.eclipse.jface.viewers.ViewerCell)
         */
        public void update(ViewerCell cell) {
            Object element = cell.getElement();
            cell.setText(getText(element));
            cell.setImage(getImage(element));
        }

        /* (non-Javadoc)
         * @see org.eclipse.pde.internal.ui.shared.target.StyledBundleLabelProvider#getImage(java.lang.Object)
         */
        public Image getImage(Object element) {
            ILabelProvider provider = (ILabelProvider) Platform.getAdapterManager().getAdapter(element,
                    ILabelProvider.class);
            if (provider != null) {
                return provider.getImage(element);
            }

            Image image = super.getImage(element);
            if (image == null) {
                image = apiToolsProvider.getImage(element);
            }

            return image;
        }

        /* (non-Javadoc)
         * @see org.eclipse.pde.internal.ui.shared.target.StyledBundleLabelProvider#getText(java.lang.Object)
         */
        public String getText(Object element) {
            ILabelProvider provider = (ILabelProvider) Platform.getAdapterManager().getAdapter(element,
                    ILabelProvider.class);
            if (provider != null) {
                return provider.getText(element);
            }

            String text = super.getText(element);
            if (text == null || text.length() == 0) {
                apiToolsProvider.getText(element);
            }

            return text;
        }

    }

    private class TargetNameLabelProvider extends StyledCellLabelProvider {

        // Definition corresponding to running host
        private TargetDefinition fRunningHost;

        private Font fTextFont;
        ApiToolsLabelProvider apiToolsProvider;

        public TargetNameLabelProvider() {
            PDEPlugin.getDefault().getLabelProvider().connect(this);

            ITargetPlatformService service = getTargetService();
            if (service != null) {
                fRunningHost = (TargetDefinition) service.newDefaultTarget();
            }

            apiToolsProvider = new ApiToolsLabelProvider() {
                protected boolean isDefaultBaseline(Object element) {
                    return isDefault(element);
                }
            };
        }

        /**
         * @return a bold dialog font
         */
        private Font getBoldFont() {
            if (fTextFont == null) {
                Font dialogFont = JFaceResources.getDialogFont();
                FontData[] fontData = dialogFont.getFontData();
                for (int i = 0; i < fontData.length; i++) {
                    FontData data = fontData[i];
                    data.setStyle(SWT.BOLD);
                }
                Display display = getShell().getDisplay();
                fTextFont = new Font(display, fontData);
            }
            return fTextFont;
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.StyledCellLabelProvider#update(org.eclipse.jface.viewers.ViewerCell)
         */
        public void update(ViewerCell cell) {
            final Object definition = cell.getElement();
            Styler style = new Styler() {
                public void applyStyles(TextStyle textStyle) {
                    int identifier = getIdentifier(definition);
                    if (newDefinitionId == identifier) {
                        textStyle.font = getBoldFont();
                    }
                }
            };

            String name = getDefinitionName(definition);

            int identifier = getIdentifier(definition);
            if (newDefinitionId == identifier) {
                name = name + NLS.bind(
                        org.eclipse.pde.api.tools.ui.internal.Messages.ApiToolsLabelProvider_default_baseline_place_holder,
                        org.eclipse.pde.api.tools.ui.internal.Messages.ApiToolsLabelProvider_default_baseline);
            }

            StyledString styledString = new StyledString(name, style);
            if (definition instanceof IApiBaseline) {
                // do nothing
            } else if (definition instanceof ITargetDefinition) {
                ITargetHandle targetHandle = ((ITargetDefinition) definition).getHandle();
                if (targetHandle instanceof WorkspaceFileTargetHandle) {
                    IFile file = ((WorkspaceFileTargetHandle) targetHandle).getTargetFile();
                    String location = " - " + file.getFullPath(); //$NON-NLS-1$
                    styledString.append(location, StyledString.DECORATIONS_STYLER);
                } else if (targetHandle instanceof ExternalFileTargetHandle) {
                    URI uri = ((ExternalFileTargetHandle) targetHandle).getLocation();
                    String location = " - " + uri.toASCIIString(); //$NON-NLS-1$
                    styledString.append(location, StyledString.DECORATIONS_STYLER);
                } else {
                    String location = (String) cell.getItem().getData(DATA_KEY_MOVED_LOCATION);
                    if (location != null) {
                        location = " - " + location; //$NON-NLS-1$
                        styledString = new StyledString(name, style);
                        styledString.append(location, StyledString.QUALIFIER_STYLER);
                    }
                }
            }

            cell.setText(styledString.toString());
            cell.setStyleRanges(styledString.getStyleRanges());
            cell.setImage(getImage(definition));
            super.update(cell);
        }

        private Image getImage(Object definition) {
            if (definition instanceof IApiBaseline) {
                return apiToolsProvider.getImage(definition);
            }

            if (definition instanceof ITargetDefinition) {
                int flag = 0;
                if (fRunningHost != null && fRunningHost.isContentEquivalent((ITargetDefinition) definition)) {
                    return PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_PRODUCT_BRANDING,
                            flag);
                }
                return PDEPlugin.getDefault().getLabelProvider().get(PDEPluginImages.DESC_TARGET_DEFINITION, flag);
            }

            return null;
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.StyledCellLabelProvider#dispose()
         */
        public void dispose() {
            PDEPlugin.getDefault().getLabelProvider().disconnect(this);
            if (fTextFont != null) {
                fTextFont.dispose();
                fTextFont = null;
            }
            super.dispose();
        }
    }

    // Table viewer
    private CheckboxTableViewer fTableViewer;

    // Buttons
    private Button fReloadButton;
    private Button fAddButton;
    private Button fEditButton;
    private Button fRemoveButton;
    private Button fMoveButton;

    // Text displaying additional information
    private TableViewer fDetails;

    //
    private ApiBaselinesConfigurationBlock compilers_ConfigBlock;

    // Initial collection of baselines, each object is realized into working copies
    private List<Object> allDefinitions;
    private Map<Integer, Object> identifiers;

    private List<ITargetDefinition> targetDefinitions;
    private List<IApiBaseline> baselineDefinitions;

    /**
     * Modified definitions (to be modified on apply) 
     */
    private List<Object> removed_Definitions;
    private Map<ITargetDefinition, IPath> moved_TargetDefinitions;

    // -1 is a special value indicating undefined
    private int activeDefinitionId = NULL_DEFINITION;
    private int newDefinitionId = NULL_DEFINITION;

    private int rebuild_Count;
    private boolean is_Dirty;

    private boolean active_ContentChanged;
    // boolean flag describing whether or not the most recent edit wizard changed the content
    // this is separate from active_ContnetChanged which describes if the content has ever changed
    private boolean wizard_ContentChanged;

    private ITargetPlatformService fTargetPlatformService;
    private IApiBaselineManager baseline_Manager;

    /* (non-Javadoc)
     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
     */
    public void init(IWorkbench workbench) {
        // ensures default targets are created when page is opened (if not created yet)
        PluginModelManager manager = PDECore.getDefault().getModelManager();
        if (!manager.isInitialized()) {
            manager.getExternalModelManager();
        }

        allDefinitions = new ArrayList<Object>();
        identifiers = new HashMap<Integer, Object>();
        // reserve -1 as a special value defining undefined
        identifiers.put(NULL_DEFINITION, new Object());

        targetDefinitions = new ArrayList<ITargetDefinition>();
        baselineDefinitions = new ArrayList<IApiBaseline>();

        removed_Definitions = new ArrayList<Object>();
        moved_TargetDefinitions = new HashMap<ITargetDefinition, IPath>(1);

        baseline_Manager = ApiPlugin.getDefault().getApiBaselineManager();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
     */
    public Control createContents(Composite parent) {
        Composite contentArea = SWTFactory.createComposite(parent);
        GridLayoutFactory.swtDefaults().margins(0, 0).applyTo(contentArea);

        createTargetProfilesGroup(contentArea);

        Dialog.applyDialogFont(contentArea);

        PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
                IHelpContextIds.TARGET_PLATFORM_PREFERENCE_PAGE);

        return contentArea;
    }

    private void createTargetProfilesGroup(Composite parent) {
        Composite comp = SWTFactory.createComposite(parent);
        GridLayoutFactory.swtDefaults().margins(0, 0).applyTo(comp);
        GridDataFactory.fillDefaults().grab(true, true).hint(350, SWT.DEFAULT).applyTo(comp);

        Label message = SWTFactory.createLabel(comp, SWT.WRAP, PDEUIMessages.TargetPlatformPreferencePage2_0);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(message);

        Label spacer = SWTFactory.createLabel(comp);
        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 1).applyTo(spacer);

        Composite tableComposite = SWTFactory.createComposite(comp);
        GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(2).applyTo(tableComposite);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(tableComposite);

        Label tableTitle = SWTFactory.createLabel(tableComposite, PDEUIMessages.TargetPlatformPreferencePage2_2);
        GridDataFactory.swtDefaults().span(2, 1).applyTo(tableTitle);

        fTableViewer = CheckboxTableViewer.newCheckList(tableComposite, SWT.MULTI | SWT.BORDER);
        GridDataFactory.fillDefaults().hint(250, SWT.DEFAULT).grab(true, true).applyTo(fTableViewer.getTable());

        fTableViewer.setLabelProvider(new TargetNameLabelProvider());
        fTableViewer.setContentProvider(ArrayContentProvider.getInstance());
        fTableViewer.addCheckStateListener(new ICheckStateListener() {
            public void checkStateChanged(CheckStateChangedEvent event) {
                Object definition = event.getElement();
                if (event.getChecked()) {
                    fTableViewer.setCheckedElements(new Object[] { definition });
                    int id = getIdentifier(definition);
                    newDefinitionId = id;
                } else {
                    fTableViewer.setChecked(definition, event.getChecked());
                    newDefinitionId = NULL_DEFINITION;
                }
                rebuild_Count = 0;
                fTableViewer.refresh(true);
                is_Dirty = true;
            }
        });
        fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                updateButtons();
                updateDetails();
            }
        });
        fTableViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                IStructuredSelection ss = (IStructuredSelection) event.getSelection();
                handleEdit(ss.getFirstElement());
            }
        });
        fTableViewer.getTable().addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent e) {
                if (e.stateMask == SWT.NONE && e.keyCode == SWT.DEL) {
                    handleRemove();
                }
            }
        });

        fTableViewer.setComparator(new ViewerComparator() {
            public int compare(Viewer viewer, Object e1, Object e2) {
                String name1 = getDefinitionName(e1);
                String name2 = getDefinitionName(e2);
                if (name1 == null) {
                    return -1;
                }
                if (name2 == null) {
                    return 1;
                }
                return name1.compareToIgnoreCase(name2);
            }
        });

        Composite buttonComposite = SWTFactory.createComposite(tableComposite);
        GridLayoutFactory.swtDefaults().margins(0, 0).applyTo(buttonComposite);
        GridDataFactory.fillDefaults().applyTo(buttonComposite);

        fReloadButton = SWTFactory.createPushButton(buttonComposite,
                PDEUIMessages.TargetPlatformPreferencePage2_16);
        int width = SWTFactory.getButtonWidthHint(fReloadButton);
        GridDataFactory.fillDefaults().hint(width, SWT.DEFAULT).applyTo(fReloadButton);
        fReloadButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleReload();
            }
        });

        spacer = SWTFactory.createLabel(buttonComposite);
        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).hint(SWT.DEFAULT, 1).applyTo(spacer);

        fAddButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.TargetPlatformPreferencePage2_3);
        GridDataFactory.fillDefaults().applyTo(fAddButton);
        fAddButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleAdd();
            }
        });

        fEditButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.TargetPlatformPreferencePage2_5);
        GridDataFactory.fillDefaults().applyTo(fEditButton);
        fEditButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleEdit(getCurrentSelection().get(0));
            }
        });

        fRemoveButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.TargetPlatformPreferencePage2_7);
        GridDataFactory.fillDefaults().applyTo(fRemoveButton);
        fRemoveButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleRemove();
            }
        });

        // TODO: Bad Label
        fMoveButton = SWTFactory.createPushButton(buttonComposite, PDEUIMessages.TargetPlatformPreferencePage2_13,
                null);
        GridDataFactory.fillDefaults().applyTo(fMoveButton);
        fMoveButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                handleMove();
            }
        });

        Composite detailsComposite = SWTFactory.createComposite(comp);
        GridLayoutFactory.swtDefaults().margins(0, 0).applyTo(detailsComposite);
        GridDataFactory.fillDefaults().applyTo(detailsComposite);

        Label locations = SWTFactory.createLabel(detailsComposite, PDEUIMessages.TargetPlatformPreferencePage2_25);
        GridDataFactory.fillDefaults().applyTo(locations);

        fDetails = new TableViewer(detailsComposite);
        GridDataFactory.fillDefaults().hint(SWT.DEFAULT, 50).grab(true, false).applyTo(fDetails.getTable());

        fDetails.setLabelProvider(new DefinitionLocationLabelProvider(true, true));
        fDetails.setContentProvider(new ArrayContentProvider());

        compilers_ConfigBlock = new ApiBaselinesConfigurationBlock((IWorkbenchPreferenceContainer) getContainer());
        compilers_ConfigBlock.createControl(comp, null);

        // Initialization steps

        // Bootstrap the buttons with their initial state
        updateButtons();

        // Add the existing API Baseline definitions
        BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
            public void run() {
                IApiBaseline[] existingBaselines = baseline_Manager.getApiBaselines();
                List<IApiBaseline> baselines = new ArrayList<IApiBaseline>(existingBaselines.length);
                Collections.addAll(baselines, existingBaselines);
                // Find any persisted (active?) baselines with the @target extension
                // and remove them from the list of baselines since they should be
                // associated with a target
                for (int i = 0; i < baselines.size(); i++) {
                    IApiBaseline baseline = baselines.get(i);
                    if (baseline.getName().endsWith(TARGET_BASELINE_EXTENSION)) {
                        baselines.remove(i--);
                    }
                }

                buildIdentifiers(baselines);
                baselineDefinitions.addAll(baselines);
                allDefinitions.addAll(baselines);
            }
        });

        // Add the existing Target definitions
        BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
            public void run() {
                ITargetPlatformService service = getTargetService();
                if (service != null) {
                    ITargetHandle[] targets = service.getTargets(null);
                    for (int i = 0; i < targets.length; i++) {
                        try {
                            ITargetDefinition target = targets[i].getTargetDefinition();
                            buildIdentifier(target);
                            targetDefinitions.add(target);
                            allDefinitions.add(target);
                        } catch (CoreException e) {
                            PDECore.log(e);
                            setErrorMessage(e.getMessage());
                        }
                    }
                }
            }
        });

        // Load the definitions into the table
        fTableViewer.setInput(allDefinitions);

        // Set the active baseline, if any
        BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
            public void run() {
                IApiBaseline activeBaseline = baseline_Manager.getDefaultApiBaseline();
                if (activeBaseline != null) {
                    if (!activeBaseline.getName().endsWith(TARGET_BASELINE_EXTENSION)) {
                        fTableViewer.setCheckedElements(new Object[] { activeBaseline });
                        activeDefinitionId = getIdentifier(activeBaseline);
                        newDefinitionId = activeDefinitionId;
                    } else {
                        int index = activeBaseline.getName().lastIndexOf(TARGET_BASELINE_EXTENSION);
                        String name = activeBaseline.getName().substring(0, index);
                        for (int i = 0; i < targetDefinitions.size(); i++) {
                            ITargetDefinition target = targetDefinitions.get(i);
                            if (target.getName().equals(name)) {
                                try {
                                    IApiBaseline tempBaseline = ApiModelFactory.newApiBaseline("local_temp"); //$NON-NLS-1$
                                    try {
                                        addComponents(tempBaseline, target, new NullProgressMonitor());
                                    } catch (CoreException ex) {
                                        // do nothing, assume they do not match
                                        continue;
                                    }

                                    // Even though they are supposed to be returned by lookup order,
                                    // the order is non-deterministic (provable, bug?) thus we need to
                                    // sort the arrays
                                    IApiComponent[] activeComponents = activeBaseline.getApiComponents();
                                    Arrays.sort(activeComponents, componentSorter);
                                    IApiComponent[] tempComponents = tempBaseline.getApiComponents();
                                    Arrays.sort(tempComponents, componentSorter);

                                    if (activeComponents.length != tempComponents.length) {
                                        continue;
                                    }

                                    boolean equal = true;
                                    for (int j = 0; j < activeComponents.length && equal; j++) {
                                        // Since we are only interested in the bundles and not any SystemLibraryComponents
                                        // we can use the overridden equals() method in BundleComponent for the evaluation
                                        // If there is a system library then this will fail, as it should since Targets
                                        // cannot have system libraries
                                        equal &= areEqual(activeComponents[j], tempComponents[j]);
                                    }

                                    if (equal) {
                                        fTableViewer.setCheckedElements(new Object[] { target });
                                        activeDefinitionId = getIdentifier(target);
                                        newDefinitionId = activeDefinitionId;
                                        break;
                                    }
                                } finally {
                                    baseline_Manager.removeApiBaseline("local_temp"); //$NON-NLS-1$
                                }
                            }
                        }
                    }
                }
            }
        });

        fTableViewer.refresh(true);
    }

    /**
     * Returns if the specified definition is the default profile or
     * not
     * 
     * @param definition
     * @return if the profile is the default or not
     */
    protected boolean isActive(Object definition) {
        int identifier = getIdentifier(definition);
        return activeDefinitionId == identifier;
    }

    /**
     * Returns if the specified definition is the default profile or
     * not
     * 
     * @param definition
     * @return if the profile is the default or not
     */
    protected boolean isDefault(Object definition) {
        int identifier = getIdentifier(definition);
        return newDefinitionId == identifier;
    }

    /**
     * @return the current selection from the table viewer
     */
    @SuppressWarnings("unchecked")
    protected List<Object> getCurrentSelection() {
        IStructuredSelection ss = (IStructuredSelection) fTableViewer.getSelection();
        if (ss.isEmpty()) {
            return new ArrayList<Object>();
        }
        return (List<Object>) ss.toList();
    }

    private void handleReload() {
        Object definition = identifiers.get(activeDefinitionId);

        if (definition instanceof IApiBaseline) {
            internalReloadBaselineDefinition((IApiBaseline) definition);
        } else if (definition instanceof ITargetDefinition) {
            internalReloadTargetDefinition((ITargetDefinition) definition);
        }
    }

    /**
     * Open the new target platform wizard
     */
    private void handleAdd() {
        NewTargetDefinitionWizard2 wizard = new NewTargetDefinitionWizard2();
        wizard.setWindowTitle(PDEUIMessages.TargetPlatformPreferencePage2_4);
        WizardDialog dialog = new WizardDialog(fAddButton.getShell(), wizard);
        if (dialog.open() == IDialogConstants.OK_ID) {
            ITargetDefinition definition = wizard.getTargetDefinition();
            if (definition != null) {
                buildIdentifier(definition);
                targetDefinitions.add(definition);
                allDefinitions.add(definition);
                fTableViewer.refresh();
                fTableViewer.setSelection(new StructuredSelection(definition), true);
                if (allDefinitions.size() == 1) {
                    int identifier = getIdentifier(definition);
                    newDefinitionId = identifier;
                    fTableViewer.setCheckedElements(new Object[] { definition });
                    fTableViewer.refresh(definition);
                    rebuild_Count = 0;
                }
                is_Dirty = true;
            }
        }
    }

    /**
     * Opens the selected target for editing
     */
    private void handleEdit(Object definition) {
        Object modifiedDefinition = null;

        wizard_ContentChanged = false;
        if (definition instanceof IApiBaseline) {
            modifiedDefinition = doEditApiBaseline((IApiBaseline) definition);
        } else if (definition instanceof ITargetDefinition) {
            modifiedDefinition = doEditTarget((ITargetDefinition) definition);
        }

        if (modifiedDefinition != null) {
            // clear any pending edit updates
            removed_Definitions.add(modifiedDefinition);
            // Replace all references to the original with the new definition
            internalRemoveDefinition(definition);
            allDefinitions.remove(definition);
            setIdentifierFor(modifiedDefinition, definition);
            internalAddDefinition(modifiedDefinition);
            allDefinitions.add(modifiedDefinition);
            fTableViewer.refresh();
            if (isActive(definition)) {
                active_ContentChanged |= wizard_ContentChanged;
            }
            if (isDefault(definition)) {
                fTableViewer.setSelection(new StructuredSelection(modifiedDefinition), true);
                fTableViewer.setCheckedElements(new Object[] { modifiedDefinition });
                rebuild_Count = 0;
                fTableViewer.refresh(true);
            }
            is_Dirty = true;
        }
    }

    /**
     * 
     * @param definition
     * @return
     */
    private IApiBaseline doEditApiBaseline(IApiBaseline definition) {
        ApiBaselineWizard wizard = new ApiBaselineWizard(definition);
        WizardDialog dialog = new WizardDialog(ApiUIPlugin.getShell(), wizard);
        if (dialog.open() == IDialogConstants.OK_ID) {
            wizard_ContentChanged = wizard.contentChanged();
            return wizard.getProfile();
        }

        return null;
    }

    /**
     * 
     * @param definition
     * @return
     */
    private ITargetDefinition doEditTarget(ITargetDefinition definition) {
        EditTargetDefinitionWizard wizard = new EditTargetDefinitionWizard(definition, true);
        wizard.setWindowTitle(PDEUIMessages.TargetPlatformPreferencePage2_6);
        WizardDialog dialog = new WizardDialog(fEditButton.getShell(), wizard);
        if (dialog.open() == IDialogConstants.OK_ID) {
            // wizard_ContentChanged = wizard.contentChanged();

            ITargetDefinition modifiedDefinition = wizard.getTargetDefinition();

            if (moved_TargetDefinitions.containsKey(definition)) {
                IPath moveLocation = moved_TargetDefinitions.remove(definition);
                moved_TargetDefinitions.put(modifiedDefinition, moveLocation);
            }

            return modifiedDefinition;
        }

        return null;
    }

    /**
     * Removes the selected targets
     */
    private void handleRemove() {
        List<Object> definitions = getCurrentSelection();

        // If we are going to remove a workspace file, prompt to ask the user first
        boolean isWorkspace = false;
        for (Iterator<Object> iterator = definitions.iterator(); iterator.hasNext();) {
            Object definition = iterator.next();
            if (definition instanceof ITargetDefinition) {
                ITargetDefinition targetDefinition = (ITargetDefinition) definition;
                if (targetDefinition.getHandle() instanceof WorkspaceFileTargetHandle) {
                    isWorkspace = true;
                    break;
                }
            }
        }

        if (isWorkspace) {
            PDEPreferencesManager preferences = new PDEPreferencesManager(IPDEUIConstants.PLUGIN_ID);
            String choice = preferences.getString(IPreferenceConstants.PROP_PROMPT_REMOVE_TARGET);
            if (!MessageDialogWithToggle.ALWAYS.equalsIgnoreCase(choice)) {
                MessageDialogWithToggle dialog = MessageDialogWithToggle.openYesNoQuestion(getShell(),
                        PDEUIMessages.TargetPlatformPreferencePage2_19,
                        PDEUIMessages.TargetPlatformPreferencePage2_20,
                        PDEUIMessages.TargetPlatformPreferencePage2_21, false,
                        PDEPlugin.getDefault().getPreferenceStore(),
                        IPreferenceConstants.PROP_PROMPT_REMOVE_TARGET);
                preferences.savePluginPreferences();
                if (dialog.getReturnCode() != IDialogConstants.YES_ID) {
                    return;
                }
            }
        }

        for (Object definition : definitions) {
            // The only thing we wont be able to tell is if they delete the active definition
            // and then do not select a new one.  To address this, if the newDefinitionId == NULL_DEFINITION
            // always set the active baseline to null to clear it out.
            if (isActive(definition)) {
                active_ContentChanged = true;
            }
            if (isDefault(definition)) {
                newDefinitionId = NULL_DEFINITION;
                rebuild_Count = 0;
            }

            removed_Definitions.add(definition);
            internalRemoveDefinition(definition);
            allDefinitions.remove(definition);
            setIdentifierFor(null, definition);
        }
        fTableViewer.refresh();

        // ... ?
        // // Quick hack because the first refresh loses the checkedState, which is being used to bold the active target
        // fTableViewer.refresh(false);
        // fTableViewer.refresh(true);
    }

    /**
     * Move the selected target to a workspace location
     */
    private void handleMove() {
        MoveTargetDefinitionWizard wizard = new MoveTargetDefinitionWizard(moved_TargetDefinitions.values());
        WizardDialog dialog = new WizardDialog(getShell(), wizard);
        dialog.create();
        SWTUtil.setDialogSize(dialog, 400, 450);
        if (dialog.open() == IDialogConstants.OK_ID) {
            TableItem ti = fTableViewer.getTable().getItem(fTableViewer.getTable().getSelectionIndex());
            IPath newTargetLoc = wizard.getTargetFileLocation();
            IFile file = PDECore.getWorkspace().getRoot().getFile(newTargetLoc);
            ti.setData(DATA_KEY_MOVED_LOCATION, file.getFullPath().toString());
            IStructuredSelection selection = (IStructuredSelection) fTableViewer.getSelection();
            moved_TargetDefinitions.put((ITargetDefinition) selection.getFirstElement(),
                    wizard.getTargetFileLocation());
            fTableViewer.refresh(true);
        }
    }

    /**
     * Update enabled state of buttons
     */
    protected void updateButtons() {
        List<Object> selection = getCurrentSelection();
        int size = selection.size();
        fEditButton.setEnabled(size == 1);
        fRemoveButton.setEnabled(size > 0);
        if (size == 1 && selection.get(0) instanceof ITargetDefinition) {
            fMoveButton.setEnabled(((ITargetDefinition) selection.get(0)).getHandle() instanceof LocalTargetHandle);
        } else {
            fMoveButton.setEnabled(false);
        }
        if (size == 1) {
            fReloadButton.setEnabled(isActive(selection.get(0)));
        } else {
            fReloadButton.setEnabled(false);
        }
    }

    /**
     * Updates the details text box with information about the currently selected target 
     */
    protected void updateDetails() {
        List<Object> selection = getCurrentSelection();
        if (selection.size() == 1) {
            fDetails.setInput(getDefinitionLocations(selection.get(0)));
        } else {
            fDetails.setInput(null);
        }
    }

    /**
     * Returns the target platform service or <code>null</code> if the service could
     * not be acquired.
     * 
     * @return target platform service or <code>null</code>
     */
    private ITargetPlatformService getTargetService() {
        // CODE_REVIEW:
        // I'm not certain what the best approach is here.  From a performance standpoint,
        // I feel as though we should cache the service once it is retrieved. However, by
        // caching it locally we violate in internal implementation of PDECore.acquireService()
        // since it immediately calls bundleContext.ungetService (bug???). Yet when retrieving
        // the same service from APIPlugin.acquireService() caching it locally would not violate
        // anything since APIPlugin does not call bundleContext.ungetService.

        if (fTargetPlatformService == null) {
            fTargetPlatformService = (ITargetPlatformService) ApiPlugin.getDefault()
                    .acquireService(ITargetPlatformService.class.getName());
        }

        // return (ITargetPlatformService) PDECore.getDefault().acquireService(ITargetPlatformService.class.getName());

        return fTargetPlatformService;
    }

    public void performDefaults() {
        performOk();
    }

    public boolean performOk() {
        // Check state conditions
        if (!is_Dirty) {
            return true;
        }

        ITargetPlatformService service = getTargetService();
        if (service == null) {
            return false;
        }

        // perform preload changes
        if (!applyChanges()) {
            return false;
        }

        compilers_ConfigBlock.performOK();

        // Since it is only possible to create new targets and not baselines
        // retrieve the baseline from the new definition (if any) and add
        // only that to the baseline manager
        IApiBaseline activeBaseline = null;
        try {
            activeBaseline = getBaselineFromDefinition(newDefinitionId);
        } catch (CoreException e) {
            setErrorMessage(e.getMessage());
            return false;
        }

        if (activeDefinitionId != newDefinitionId || active_ContentChanged) {
            baseline_Manager.setDefaultApiBaseline(activeBaseline.getName());

            if (rebuild_Count < 1) {
                rebuild_Count++;
                IProject[] projects = Util.getApiProjects();
                // do not even ask if there are no projects to build
                if (projects != null) {
                    if (MessageDialog.openQuestion(getShell(), PreferenceMessages.ApiProfilesPreferencePage_6,
                            PreferenceMessages.ApiProfilesPreferencePage_7)) {
                        Util.getBuildJob(projects).schedule();
                    }
                }
            }
        }

        activeDefinitionId = newDefinitionId;
        is_Dirty = false;
        active_ContentChanged = false;

        return super.performOk();
    }

    private boolean applyChanges() {
        internalMoveDefinitions();

        try {
            internalRemoveDefinitions();
        } catch (CoreException e) {
            ErrorDialog.openError(getShell(), PDEUIMessages.TargetPlatformPreferencePage2_8,
                    PDEUIMessages.TargetPlatformPreferencePage2_11, e.getStatus());
            return false;
        }

        try {
            internalSaveDefinitions();
        } catch (CoreException e) {
            setErrorMessage(e.getMessage());
            return false;
        }

        return true;
    }

    private void internalMoveDefinitions() {
        ITargetPlatformService service = getTargetService();

        // Move the marked definitions to workspace
        if (moved_TargetDefinitions.size() > 0) {
            Iterator<ITargetDefinition> iterator = moved_TargetDefinitions.keySet().iterator();
            while (iterator.hasNext()) {
                try {
                    ITargetDefinition target = iterator.next();
                    IPath path = moved_TargetDefinitions.get(target);
                    IFile targetFile = PDECore.getWorkspace().getRoot().getFile(path);

                    WorkspaceFileTargetHandle wrkspcTargetHandle = new WorkspaceFileTargetHandle(targetFile);
                    ITargetDefinition newTarget = service.newTarget();
                    service.copyTargetDefinition(target, newTarget);
                    wrkspcTargetHandle.save(newTarget);

                    // clear any pending edit updates
                    removed_Definitions.add(target);
                    // Replace all references to the original with the new definition
                    internalRemoveDefinition(target);
                    allDefinitions.remove(target);

                    ITargetDefinition workspaceTarget = wrkspcTargetHandle.getTargetDefinition();
                    setIdentifierFor(workspaceTarget, target);
                    internalAddDefinition(workspaceTarget);
                    allDefinitions.add(workspaceTarget);

                    fTableViewer.refresh(false);
                    // if (target == fActiveTarget) {
                    //    load = true;
                    //    toLoad = workspaceTarget;
                    // }
                } catch (CoreException e) {
                    PDEPlugin.log(e);
                }
            }
        }

        moved_TargetDefinitions.clear();
    }

    private void internalRemoveDefinitions() throws CoreException {
        // Remove any definitions that have been removed
        Iterator<Object> iterator = removed_Definitions.iterator();
        while (iterator.hasNext()) {
            Object definition = iterator.next();

            if (definition instanceof IApiBaseline) {
                String baselineName = ((IApiBaseline) definition).getName();
                baseline_Manager.removeApiBaseline(baselineName);
            } else if (definition instanceof ITargetDefinition) {
                ITargetPlatformService service = getTargetService();
                ITargetDefinition target = (ITargetDefinition) definition;
                service.deleteTarget(target.getHandle());
            }

            throw new IllegalStateException(
                    "Remove Definitions - Unknown definition type: " + definition.toString());
        }

        removed_Definitions.clear();
    }

    private void internalSaveDefinitions() throws CoreException {
        ITargetPlatformService service = getTargetService();

        // save others that are dirty
        Iterator<ITargetDefinition> iterator = targetDefinitions.iterator();
        while (iterator.hasNext()) {
            ITargetDefinition def = iterator.next();
            boolean save = true;
            if (def.getHandle().exists()) {
                ITargetDefinition original = def.getHandle().getTargetDefinition();
                if (((TargetDefinition) original).isContentEqual(def)) {
                    save = false;
                }
            }
            if (save) {
                service.saveTargetDefinition(def);
            }
        }
    }

    private void internalReloadTargetDefinition(final ITargetDefinition target) {
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell()) {
            protected void configureShell(Shell shell) {
                super.configureShell(shell);
                shell.setText(PDEUIMessages.TargetPlatformPreferencePage2_12);
            }
        };
        try {
            dialog.run(true, true, new IRunnableWithProgress() {
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    if (monitor.isCanceled()) {
                        throw new InterruptedException();
                    }
                    // Resolve the target
                    target.resolve(monitor);
                    if (monitor.isCanceled()) {
                        throw new InterruptedException();
                    }
                }
            });
        } catch (InvocationTargetException e) {
            PDEPlugin.log(e);
            setErrorMessage(e.getMessage());
        } catch (InterruptedException e) {
            // Do nothing, resolve will happen when user presses ok
        }

        if (target.isResolved()) {
            // Check if the bundle resolution has errors
            IStatus bundleStatus = target.getStatus();
            if (bundleStatus.getSeverity() == IStatus.ERROR) {
                ErrorDialog.openError(getShell(), PDEUIMessages.TargetPlatformPreferencePage2_14,
                        PDEUIMessages.TargetPlatformPreferencePage2_15, bundleStatus, IStatus.ERROR);
            }
        }
        fTableViewer.refresh(true);
    }

    private void internalReloadBaselineDefinition(IApiBaseline baseline) {

    }

    private IApiBaseline getBaselineFromDefinition(int identifier) throws CoreException {
        Object definition = identifiers.get(identifier);

        if (definition instanceof IApiBaseline) {
            return (IApiBaseline) definition;
        }

        if (!(definition instanceof ITargetDefinition)) {
            throw new IllegalStateException("Unknown definition type: " + definition.toString());
        }

        ITargetDefinition targetDefinition = (ITargetDefinition) definition;

        // Create the ApiBaseline to be used for the target
        IApiBaseline baseline = ApiModelFactory.newApiBaseline(targetDefinition.getName() + "@target");

        IProgressMonitor monitor = new NullProgressMonitor();
        addComponents(baseline, targetDefinition, monitor);

        return baseline;
    }

    /**
     * 
     * @param definitions
     */
    private void buildIdentifiers(List<? extends Object> definitions) {
        for (int i = 0; i < definitions.size(); i++) {
            buildIdentifier(definitions.get(i));
        }
    }

    /**
     * 
     * @param definition
     */
    private void buildIdentifier(Object definition) {
        int hash = definition.hashCode();
        Object collision = identifiers.get(hash);
        while (collision != null) {
            collision = identifiers.get(++hash);
        }

        identifiers.put(hash, definition);
    }

    /**
     * 
     * @param definition
     * @return
     */
    private int getIdentifier(Object definition) {
        Iterator<Entry<Integer, Object>> entries = identifiers.entrySet().iterator();
        while (entries.hasNext()) {
            Entry<Integer, Object> entry = entries.next();
            if (definition == entry.getValue()) {
                return entry.getKey();
            }
        }

        throw new IllegalStateException(
                "The specified definition is not in the list of existing definitions! " + definition.toString());
    }

    /**
     * 
     * @param newDefinition
     * @param oldDefinition
     */
    private void setIdentifierFor(Object newDefinition, Object oldDefinition) {
        int identifier = getIdentifier(oldDefinition);

        if (newDefinition == null) {
            identifiers.remove(identifier);
        } else {
            identifiers.put(identifier, newDefinition);
        }
    }

    /**
     * 
     * @param definition
     * @return
     */
    private String getDefinitionName(Object definition) {
        if (definition instanceof IApiBaseline) {
            return ((IApiBaseline) definition).getName();
        }

        if (definition instanceof ITargetDefinition) {
            String name = ((ITargetDefinition) definition).getName();
            if (name == null || name.length() == 0) {
                ITargetHandle targetHandle = ((ITargetDefinition) definition).getHandle();
                name = targetHandle.toString();
            }
            return name;
        }

        return null;
    }

    /**
     * 
     * @param definition
     * @return
     */
    private Object[] getDefinitionLocations(Object definition) {
        if (definition instanceof IApiBaseline) {
            String location = ((IApiBaseline) definition).getLocation();
            return new String[] { location };
        }

        if (definition instanceof ITargetDefinition) {
            return ((ITargetDefinition) definition).getTargetLocations();
        }

        return null;
    }

    /**
     * 
     * @param definition
     */
    private void internalRemoveDefinition(Object definition) {
        if (definition instanceof IApiBaseline) {
            baselineDefinitions.remove((IApiBaseline) definition);
        } else if (definition instanceof ITargetDefinition) {
            targetDefinitions.remove((ITargetDefinition) definition);
        }
    }

    /**
     * 
     * @param definition
     */
    private void internalAddDefinition(Object definition) {
        if (definition instanceof IApiBaseline) {
            baselineDefinitions.add((IApiBaseline) definition);
        } else if (definition instanceof ITargetDefinition) {
            targetDefinitions.add((ITargetDefinition) definition);
        }
    }

}