/******************************************************************************* * Copyright (c) 2009 QNX Software Systems 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: * QNX Software Systems - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.ui.workingsets; import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.ATTR_NAME; import static org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationManager.KEY_CONFIG; import java.util.Collection; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.ui.IMemento; import org.eclipse.ui.IWorkingSet; import com.ibm.icu.text.UCharacterIterator; import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; /** * Default implementation of the {@link IWorkingSetProxy} interface. * * @noextend This class is not intended to be subclassed by clients. * * @author Christian W. Damus (cdamus) * * @since 6.0 */ public class WorkingSetProxy implements IWorkingSetProxy { private String name; private Map<String, IWorkingSetConfiguration> configurations; /** * Initializes me. */ public WorkingSetProxy() { super(); } public String getName() { return name; } /** * Sets my name. This <b>does not</b> change the name of the working set that I represent. Rather, it * changes <i>which</i> working set I represent. * * @param name * my new name */ void setName(String name) { this.name = name; } public IWorkingSet resolve() { return WorkingSetConfigurationManager.WS_MGR.getWorkingSet(name); } public Collection<IProject> resolveProjects() { Set<IProject> result = new java.util.HashSet<IProject>(); IWorkingSet resolvedWS = resolve(); if (resolvedWS != null) { for (IAdaptable next : resolvedWS.getElements()) { IProject proj = (IProject) next.getAdapter(IProject.class); if (proj != null) { result.add(proj); } } } return result; } public boolean isValid() { return !resolveProjects().isEmpty(); } private Map<String, IWorkingSetConfiguration> getConfigurationsMap() { if (configurations == null) { configurations = new java.util.HashMap<String, IWorkingSetConfiguration>(); } return configurations; } public IWorkingSetConfiguration getConfiguration(String name) { return getConfigurationsMap().get(name); } public Collection<IWorkingSetConfiguration> getConfigurations() { return getConfigurationsMap().values(); } public void saveState(IMemento memento) { memento.putString(ATTR_NAME, getName()); for (IWorkingSetConfiguration next : getConfigurations()) { if (!isTransient(next)) { next.saveState(memento.createChild(KEY_CONFIG)); } } } /** * Queries whether the specified configuration is transient, meaning that it should not be persisted in * the working set configuration store. The default implementation just returns <code>false</code>; * subclasses may redefine as required. * * @param config * a working set configuration * @return whether it should be omitted from persistence */ protected boolean isTransient(IWorkingSetConfiguration config) { return false; } public void loadState(IMemento memento) { setName(memento.getString(ATTR_NAME)); for (IMemento next : memento.getChildren(KEY_CONFIG)) { IWorkingSetConfiguration config = createWorkingSetConfiguration(); config.loadState(next); getConfigurationsMap().put(config.getName(), config); } } /** * Creates a new child working set configuration element. Subclasses may override to create custom * implementations. * * @return the new working set configuration */ protected IWorkingSetConfiguration createWorkingSetConfiguration() { return new WorkingSetConfiguration(this); } /** * Provides simple access to the child configurations, to remove the specified configuration. * * @param config * a configuration to remove */ protected void basicRemoveConfiguration(IWorkingSetConfiguration config) { getConfigurationsMap().remove(config.getName()); } /** * Provides simple access to the child configurations, to add the specified configuration. * * @param config * a configuration to add */ protected void basicAddConfiguration(IWorkingSetConfiguration config) { getConfigurationsMap().put(config.getName(), config); } public ISnapshot createSnapshot(WorkspaceSnapshot workspace) { Snapshot result = new Snapshot(this, workspace); result.updateActiveConfigurations(); return result; } // // Nested classes // /** * The default implementation of a mutable working set snapshot. * * @noextend This class is not intended to be subclassed by clients. * * @author Christian W. Damus (cdamus) * * @since 6.0 */ public static class Snapshot extends WorkingSetProxy implements IWorkingSetProxy.ISnapshot { private final WorkspaceSnapshot workspace; private IWorkingSetConfiguration.ISnapshot readOnlyConfig; /** * Initializes me with the current workspace snapshot. * * @param workingSet * the original working set element to copy * @param workspace * the workspace snapshot */ protected Snapshot(IWorkingSetProxy workingSet, WorkspaceSnapshot workspace) { super(); this.workspace = workspace; setName(workingSet.getName()); for (IWorkingSetConfiguration next : workingSet.getConfigurations()) { basicAddConfiguration(next.createSnapshot(this, workspace)); } } public final WorkspaceSnapshot getWorkspaceSnapshot() { return workspace; } public IWorkingSetConfiguration.ISnapshot createConfiguration(String name) { if ((name == null) || (name.length() == 0)) { throw new IllegalArgumentException("name is empty"); //$NON-NLS-1$ } if (getConfiguration(name) != null) { throw new IllegalArgumentException("name is already in use"); //$NON-NLS-1$ } IWorkingSetConfiguration.ISnapshot result = createWorkingSetConfiguration(); result.setName(name); heuristicSelectProjectConfigurations(result); basicAddConfiguration(result); updateActiveConfigurations(); return result; } /** * Heuristically attempts to select reasonable default project configurations for a new working-set * configuration. This implementation does a best-effort match of project configuration names against * the working set configuration name. * * @param newConfig * the new working set configuration */ protected void heuristicSelectProjectConfigurations(IWorkingSetConfiguration.ISnapshot newConfig) { String nameToSearch = getSearchKey(newConfig.getName()); for (IWorkingSetProjectConfiguration next : newConfig.getProjectConfigurations()) { IWorkingSetProjectConfiguration.ISnapshot project = (IWorkingSetProjectConfiguration.ISnapshot) next; for (ICConfigurationDescription config : project.resolveConfigurations()) { if (nameToSearch.equalsIgnoreCase(getSearchKey(config.getName()))) { // a match! Select this config project.setSelectedConfigurationID(config.getId()); break; } } } } private String getSearchKey(String configurationName) { StringBuilder result = new StringBuilder(configurationName.length()); UCharacterIterator iter = UCharacterIterator.getInstance(configurationName); for (int cp = iter.nextCodePoint(); cp != UCharacterIterator.DONE; cp = iter.nextCodePoint()) { if (Character.isLetterOrDigit(cp)) { result.appendCodePoint(cp); } } return result.toString(); } /** * I create working-set configuration snapshots that are mutable, as I am. */ @Override protected IWorkingSetConfiguration.ISnapshot createWorkingSetConfiguration() { return new WorkingSetConfiguration.Snapshot(this, workspace); } public void removeConfiguration(IWorkingSetConfiguration config) { if (WorkingSetConfiguration.isReadOnly(config)) { throw new IllegalArgumentException("config is read-only"); //$NON-NLS-1$ } basicRemoveConfiguration(config); } public boolean updateActiveConfigurations() { boolean result = getConfigurations().isEmpty(); boolean hasActiveConfig = false; for (IWorkingSetConfiguration next : getConfigurations()) { if (next.isActive() && !WorkingSetConfiguration.isReadOnly(next)) { hasActiveConfig = true; break; } } if (hasActiveConfig) { if (readOnlyConfig != null) { basicRemoveConfiguration(readOnlyConfig); result = true; } readOnlyConfig = null; } else { WorkingSetConfiguration.Snapshot ro = new WorkingSetConfiguration.Snapshot(this, workspace, true); ro.basicSetName(""); // don't want to validate this name //$NON-NLS-1$ readOnlyConfig = ro; basicAddConfiguration(readOnlyConfig); result = true; } return result; } /** * Read-only working set configuration snapshots are transient. */ @Override protected boolean isTransient(IWorkingSetConfiguration config) { return WorkingSetConfiguration.isReadOnly(config); } } }