| /* |
| * Copyright (c) 2014-2018 Eike Stepper (Loehne, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v20.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.oomph.setup.impl; |
| |
| import org.eclipse.oomph.internal.setup.SetupPrompter; |
| import org.eclipse.oomph.preferences.PreferencesFactory; |
| import org.eclipse.oomph.preferences.util.PreferencesUtil; |
| import org.eclipse.oomph.preferences.util.PreferencesUtil.PreferenceProperty; |
| import org.eclipse.oomph.setup.Installation; |
| import org.eclipse.oomph.setup.PreferenceTask; |
| import org.eclipse.oomph.setup.SetupPackage; |
| import org.eclipse.oomph.setup.SetupTask; |
| import org.eclipse.oomph.setup.SetupTaskContext; |
| import org.eclipse.oomph.setup.Trigger; |
| import org.eclipse.oomph.setup.User; |
| import org.eclipse.oomph.setup.VariableTask; |
| import org.eclipse.oomph.setup.Workspace; |
| import org.eclipse.oomph.setup.impl.PreferenceTaskImpl.PreferenceHandler.Factory; |
| import org.eclipse.oomph.util.OS; |
| import org.eclipse.oomph.util.ObjectUtil; |
| import org.eclipse.oomph.util.ReflectUtil; |
| import org.eclipse.oomph.util.StringUtil; |
| import org.eclipse.oomph.util.UserCallback; |
| import org.eclipse.oomph.util.XMLUtil; |
| |
| import org.eclipse.emf.common.CommonPlugin; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.util.BasicEList; |
| import org.eclipse.emf.common.util.BasicEMap; |
| import org.eclipse.emf.common.util.CommonUtil; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.impl.ENotificationImpl; |
| import org.eclipse.emf.ecore.resource.URIConverter; |
| |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| 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.content.IContentType; |
| |
| import org.osgi.service.prefs.Preferences; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.ErrorHandler; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.SAXParseException; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| |
| import java.io.File; |
| import java.io.StringReader; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeSet; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| /** |
| * <!-- begin-user-doc --> |
| * An implementation of the model object '<em><b>Eclipse Preference Task</b></em>'. |
| * <!-- end-user-doc --> |
| * <p> |
| * The following features are implemented: |
| * </p> |
| * <ul> |
| * <li>{@link org.eclipse.oomph.setup.impl.PreferenceTaskImpl#getKey <em>Key</em>}</li> |
| * <li>{@link org.eclipse.oomph.setup.impl.PreferenceTaskImpl#getValue <em>Value</em>}</li> |
| * </ul> |
| * |
| * @generated |
| */ |
| public class PreferenceTaskImpl extends SetupTaskImpl implements PreferenceTask |
| { |
| /** |
| * The default value of the '{@link #getKey() <em>Key</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getKey() |
| * @generated |
| * @ordered |
| */ |
| protected static final String KEY_EDEFAULT = null; |
| |
| /** |
| * The cached value of the '{@link #getKey() <em>Key</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getKey() |
| * @generated |
| * @ordered |
| */ |
| protected String key = KEY_EDEFAULT; |
| |
| /** |
| * The default value of the '{@link #getValue() <em>Value</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getValue() |
| * @generated |
| * @ordered |
| */ |
| protected static final String VALUE_EDEFAULT = null; |
| |
| /** |
| * The cached value of the '{@link #getValue() <em>Value</em>}' attribute. |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @see #getValue() |
| * @generated |
| * @ordered |
| */ |
| protected String value = VALUE_EDEFAULT; |
| |
| private transient PreferencesUtil.PreferenceProperty preferenceProperty; |
| |
| private transient PreferenceHandler preferenceHandler; |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| protected PreferenceTaskImpl() |
| { |
| super(); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| protected EClass eStaticClass() |
| { |
| return SetupPackage.Literals.PREFERENCE_TASK; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public String getKey() |
| { |
| return key; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setKeyGen(String newKey) |
| { |
| String oldKey = key; |
| key = newKey; |
| if (eNotificationRequired()) |
| { |
| eNotify(new ENotificationImpl(this, Notification.SET, SetupPackage.PREFERENCE_TASK__KEY, oldKey, key)); |
| } |
| } |
| |
| public void setKey(String newKey) |
| { |
| setKeyGen(CommonUtil.intern(newKey)); |
| preferenceHandler = null; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public String getValue() |
| { |
| return value; |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| public void setValue(String newValue) |
| { |
| String oldValue = value; |
| value = newValue; |
| if (eNotificationRequired()) |
| { |
| eNotify(new ENotificationImpl(this, Notification.SET, SetupPackage.PREFERENCE_TASK__VALUE, oldValue, value)); |
| } |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public Object eGet(int featureID, boolean resolve, boolean coreType) |
| { |
| switch (featureID) |
| { |
| case SetupPackage.PREFERENCE_TASK__KEY: |
| return getKey(); |
| case SetupPackage.PREFERENCE_TASK__VALUE: |
| return getValue(); |
| } |
| return super.eGet(featureID, resolve, coreType); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public void eSet(int featureID, Object newValue) |
| { |
| switch (featureID) |
| { |
| case SetupPackage.PREFERENCE_TASK__KEY: |
| setKey((String)newValue); |
| return; |
| case SetupPackage.PREFERENCE_TASK__VALUE: |
| setValue((String)newValue); |
| return; |
| } |
| super.eSet(featureID, newValue); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public void eUnset(int featureID) |
| { |
| switch (featureID) |
| { |
| case SetupPackage.PREFERENCE_TASK__KEY: |
| setKey(KEY_EDEFAULT); |
| return; |
| case SetupPackage.PREFERENCE_TASK__VALUE: |
| setValue(VALUE_EDEFAULT); |
| return; |
| } |
| super.eUnset(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public boolean eIsSet(int featureID) |
| { |
| switch (featureID) |
| { |
| case SetupPackage.PREFERENCE_TASK__KEY: |
| return KEY_EDEFAULT == null ? key != null : !KEY_EDEFAULT.equals(key); |
| case SetupPackage.PREFERENCE_TASK__VALUE: |
| return VALUE_EDEFAULT == null ? value != null : !VALUE_EDEFAULT.equals(value); |
| } |
| return super.eIsSet(featureID); |
| } |
| |
| /** |
| * <!-- begin-user-doc --> |
| * <!-- end-user-doc --> |
| * @generated |
| */ |
| @Override |
| public String toString() |
| { |
| if (eIsProxy()) |
| { |
| return super.toString(); |
| } |
| |
| StringBuilder result = new StringBuilder(super.toString()); |
| result.append(" (key: "); |
| result.append(key); |
| result.append(", value: "); |
| result.append(value); |
| result.append(')'); |
| return result.toString(); |
| } |
| |
| @Override |
| public int getPriority() |
| { |
| return getPreferenceHandler().getPriority(); |
| } |
| |
| private PreferenceHandler getPreferenceHandler() |
| { |
| if (preferenceHandler == null) |
| { |
| preferenceHandler = PreferenceHandler.getHandler(getKey()); |
| } |
| |
| return preferenceHandler; |
| } |
| |
| @Override |
| public Object getOverrideToken() |
| { |
| return createToken(getKey()); |
| } |
| |
| @Override |
| public void overrideFor(SetupTask overriddenSetupTask) |
| { |
| super.overrideFor(overriddenSetupTask); |
| |
| PreferenceTask overriddenPeferenceTask = (PreferenceTask)overriddenSetupTask; |
| PreferenceHandler preferenceHandler = getPreferenceHandler(); |
| if (preferenceHandler.isNeeded(overriddenPeferenceTask.getValue(), getValue())) |
| { |
| setValue(preferenceHandler.merge()); |
| } |
| } |
| |
| @Override |
| public int getProgressMonitorWork() |
| { |
| return 0; |
| } |
| |
| public boolean isNeeded(SetupTaskContext context) throws Exception |
| { |
| if (StringUtil.isEmpty(key)) |
| { |
| return false; |
| } |
| |
| preferenceProperty = new PreferencesUtil.PreferenceProperty(key); |
| |
| String oldValue = preferenceProperty.getEffectiveProperty().get(null); |
| String newValue = getValue(); |
| return getPreferenceHandler().isNeeded(oldValue, newValue); |
| } |
| |
| public void perform(SetupTaskContext context) throws Exception |
| { |
| final String key = getKey(); |
| |
| // Ignore project-specific preferences for projects that don't exist in the workspace. |
| URI uri = PreferencesFactory.eINSTANCE.createURI(key); |
| if ("project".equals(uri.authority())) |
| { |
| if (!ResourcesPlugin.getWorkspace().getRoot().getProject(URI.decode(uri.segment(0))).isAccessible()) |
| { |
| context.log("Ignoring preference " + key + " = " + value); |
| return; |
| } |
| } |
| |
| final String value = getValue(); |
| if (value != null && value.indexOf('\n') != -1) |
| { |
| context.log(value); |
| } |
| |
| performUI(context, new RunnableWithContext() |
| { |
| public void run(SetupTaskContext context) throws Exception |
| { |
| String mergedValue = preferenceHandler.merge(); |
| preferenceProperty.set(mergedValue); |
| preferenceHandler.apply(context); |
| } |
| }); |
| |
| Preferences node = preferenceProperty.getNode(); |
| node.flush(); |
| } |
| |
| public boolean execute(final UserCallback callback) throws Exception |
| { |
| SetupTaskContext context = new SetupTaskContext() |
| { |
| public boolean isCanceled() |
| { |
| return false; |
| } |
| |
| public void log(String line) |
| { |
| // Do nothing. |
| } |
| |
| public void log(String line, Severity severity) |
| { |
| // Do nothing. |
| } |
| |
| public void log(String line, boolean filter) |
| { |
| // Do nothing. |
| } |
| |
| public void log(String line, boolean filter, Severity severity) |
| { |
| // Do nothing. |
| } |
| |
| public void log(IStatus status) |
| { |
| // Do nothing. |
| } |
| |
| public void log(Throwable t) |
| { |
| // Do nothing. |
| } |
| |
| public void task(SetupTask setupTask) |
| { |
| // Do nothing. |
| } |
| |
| public void setTerminating() |
| { |
| // Do nothing. |
| } |
| |
| public IProgressMonitor getProgressMonitor(boolean working) |
| { |
| return new NullProgressMonitor(); |
| } |
| |
| public SetupPrompter getPrompter() |
| { |
| return new SetupPrompter() |
| { |
| public OS getOS() |
| { |
| return OS.INSTANCE; |
| } |
| |
| public String getVMPath() |
| { |
| return null; |
| } |
| |
| public UserCallback getUserCallback() |
| { |
| return callback; |
| } |
| |
| public String getValue(VariableTask variable) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean promptVariables(List<? extends SetupTaskContext> performers) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| } |
| |
| public Trigger getTrigger() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public void checkCancelation() |
| { |
| // Do nothing. |
| } |
| |
| public boolean isSelfHosting() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean isPerforming() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean isOffline() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean isMirrors() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean isRestartNeeded() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public void setRestartNeeded(String reason) |
| { |
| // Do nothing. |
| } |
| |
| public User getUser() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public Workspace getWorkspace() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public Installation getInstallation() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public File getInstallationLocation() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public File getProductLocation() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public File getProductConfigurationLocation() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public File getWorkspaceLocation() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public String getRelativeProductFolder() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public OS getOS() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public URIConverter getURIConverter() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public URI redirect(URI uri) |
| { |
| return uri; |
| } |
| |
| public String redirect(String uri) |
| { |
| return uri; |
| } |
| |
| public Object get(Object key) |
| { |
| return null; |
| } |
| |
| public Object put(Object key, Object value) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public Set<Object> keySet() |
| { |
| return Collections.emptySet(); |
| } |
| |
| public String getLauncherName() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean matchesFilterContext(String filter) |
| { |
| return false; |
| } |
| }; |
| |
| if (isNeeded(context)) |
| { |
| perform(context); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Pathological list preferences: |
| * <ul> |
| * <li> //instance/org.eclipse.ui.browser/browsers (order matters for //instance/org.eclipse.ui.browser/browser-choice) |
| * <li> //instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.taskTags (order matters for //instance/org.eclipse.jdt.core/org.eclipse.jdt.core.compiler.taskPriorities) |
| * <li> //instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.typefilter.disabled (enabling an item does not remove the item) |
| * <li> //instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.typefilter.enabled (disabling an item does not remove the item) |
| * </ul> |
| * |
| * @author Ed Merks |
| */ |
| public static class PreferenceHandler |
| { |
| protected URI key; |
| |
| protected String oldValue; |
| |
| protected String newValue; |
| |
| public PreferenceHandler(URI key) |
| { |
| this.key = key; |
| } |
| |
| public int getPriority() |
| { |
| return key != null && "project".equals(key.authority()) ? PRIORITY_LATE : PRIORITY_EARLY; |
| } |
| |
| public boolean isIgnored() |
| { |
| return false; |
| } |
| |
| public final boolean isNeeded(String oldValue, String newValue) |
| { |
| this.oldValue = oldValue; |
| this.newValue = newValue; |
| return isNeeded(); |
| } |
| |
| protected boolean isNeeded() |
| { |
| if (isExcluded()) |
| { |
| return false; |
| } |
| |
| String mergedValue = merge(); |
| return !ObjectUtil.equals(mergedValue, oldValue); |
| } |
| |
| protected boolean isExcluded() |
| { |
| // If the old value is an XML blob... |
| if (oldValue != null && oldValue.startsWith("<?xml ")) |
| { |
| try |
| { |
| DocumentBuilder documentBuilder = XMLUtil.createDocumentBuilder(); |
| documentBuilder.setErrorHandler(new ErrorHandler() |
| { |
| public void warning(SAXParseException exception) throws SAXException |
| { |
| } |
| |
| public void fatalError(SAXParseException exception) throws SAXException |
| { |
| throw exception; |
| } |
| |
| public void error(SAXParseException exception) throws SAXException |
| { |
| } |
| }); |
| Document document = documentBuilder.parse(new InputSource(new StringReader(oldValue))); |
| NodeList childNodes = document.getDocumentElement().getChildNodes(); |
| for (int i = 0, length = childNodes.getLength(); i < length; ++i) |
| { |
| Node item = childNodes.item(i); |
| String nodeValue = item.getNodeValue(); |
| |
| // If there are any children that aren't simply whitespace content, then it's non-empty XML. |
| if (nodeValue == null || nodeValue.trim().length() != 0) |
| { |
| return true; |
| } |
| } |
| } |
| catch (Throwable throwable) |
| { |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| return false; |
| } |
| |
| public String merge() |
| { |
| return newValue; |
| } |
| |
| public String delta() |
| { |
| return newValue; |
| } |
| |
| public void apply(SetupTaskContext context) |
| { |
| } |
| |
| public static void main(String[] args) |
| { |
| PreferenceHandlerFactoryRegistry uriMappingRegistryImpl = (PreferenceHandlerFactoryRegistry)Factory.Registry.INSTANCE; |
| uriMappingRegistryImpl.put(URI.createURI("//"), null); |
| uriMappingRegistryImpl.put(URI.createURI("///"), null); |
| uriMappingRegistryImpl.put(URI.createURI("//instance/foo/bar/"), null); |
| uriMappingRegistryImpl.put(URI.createURI("//instance"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return null; |
| } |
| }); |
| |
| uriMappingRegistryImpl.getFactory(URI.createURI("//instance/foo/bar/myproperty")); |
| uriMappingRegistryImpl.getFactory(URI.createURI("//instance/fudge/bar/myproperty")); |
| |
| { |
| PreferenceHandler handler = new ListPreferenceHandler(URI.createURI(""), "(?s)([^\\n]+\\n[0-9]+)", "([^\n]+)", "\n"); |
| if (handler.isNeeded("a\n2\n", "b\n2\na\n1\n")) |
| { |
| String result = handler.merge(); |
| System.out.println(result); |
| } |
| else |
| { |
| System.out.println("has conflict"); |
| } |
| } |
| |
| { |
| PreferenceHandler handler = new ListPreferenceHandler(URI.createURI(""), "(?s)([^\\n]+\\n[0-9]+)", "([^ \n]+) ([^\n]+)", "\n"); |
| if (handler.isNeeded("a b\n2\n", "a b\n3\nb a\n2\na a\n1\n")) |
| { |
| String result = handler.merge(); |
| System.out.println(result); |
| } |
| else |
| { |
| System.out.println("has conflict"); |
| } |
| } |
| } |
| |
| public static PreferenceHandler getHandler(String key) |
| { |
| URI keyURI = PreferencesFactory.eINSTANCE.createURI(key); |
| return getHandler(keyURI); |
| } |
| |
| public static PreferenceHandler getHandler(URI key) |
| { |
| Factory factory = Factory.Registry.INSTANCE.getFactory(key); |
| if (factory == null) |
| { |
| return new PreferenceHandler(key); |
| } |
| |
| return factory.create(key); |
| } |
| |
| protected static void registerListHandlerFactory(String key, char itemSeparator, char keySeparator) |
| { |
| final String itemSeparatorStr = new String(new char[] { itemSeparator }); |
| final String itemPattern = "([^" + itemSeparatorStr + "]+)"; |
| final String keyPattern = keySeparator == (char)0 ? "(.*)" : "([^" + new String(new char[] { keySeparator }) + "]+)"; |
| |
| PreferenceHandlerFactoryRegistry registry = (PreferenceHandlerFactoryRegistry)Factory.Registry.INSTANCE; |
| registry.put(URI.createURI(key), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new ListPreferenceHandler(key, itemPattern, keyPattern, itemSeparatorStr); |
| } |
| }); |
| } |
| |
| protected static void registerListHandlerFactory(String key, char itemSeparator) |
| { |
| registerListHandlerFactory(key, itemSeparator, (char)0); |
| } |
| |
| static |
| { |
| PreferenceHandlerFactoryRegistry registry = (PreferenceHandlerFactoryRegistry)Factory.Registry.INSTANCE; |
| registry.put(URI.createURI("//"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new PreferenceHandler(key); |
| } |
| }); |
| |
| registerListHandlerFactory("//instance/org.eclipse.ui.workbench/ENABLED_DECORATORS", ',', ':'); |
| registerListHandlerFactory("//instance/org.eclipse.ui.navigator/org.eclipse.ui.navigator.ProjectExplorer.activatedExtensions", ';', '='); |
| registerListHandlerFactory("//instance/org.eclipse.ui.navigator/org.eclipse.ui.navigator.ProjectExplorer.filterActivation", ':'); |
| |
| // See Javadoc on PreferenceHandler: |
| // registerListHandlerFactory("//instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.typefilter.disabled", ';'); |
| // registerListHandlerFactory("//instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.typefilter.enabled", ';'); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.ui.workbench/"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| String lastSegment = key.lastSegment(); |
| if ("editors".equals(lastSegment)) |
| { |
| return new IgnoredPreferenceHandler(key); |
| } |
| |
| if ("resourcetypes".equals(lastSegment)) |
| { |
| return new XMLPreferenceHandler(key, "info", new String[] { "extension", "name" }, null); |
| } |
| |
| if ("org.eclipse.ui.commands".equals(lastSegment)) |
| { |
| return new PreferenceHandler(key) |
| { |
| @Override |
| protected boolean isExcluded() |
| { |
| return false; |
| } |
| }; |
| } |
| |
| return new PreferenceHandler(key); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.core.runtime/content-types/"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| if (key.segmentCount() == 4) |
| { |
| String property = key.lastSegment(); |
| if (property.equals("file-extensions") || property.equals("file-names")) |
| { |
| return new ContentTypeFileExtensionPreferenceHandler(key); |
| } |
| |
| if (property.equals("charset")) |
| { |
| return new ContentTypeCharsetPreferenceHandler(key); |
| } |
| } |
| |
| return new PreferenceHandler(key); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.core/"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| String lastSegment = key.lastSegment(); |
| if (lastSegment.startsWith("org.eclipse.jdt.core.formatter.")) |
| { |
| return new IgnoredPreferenceHandler(key); |
| } |
| |
| return new PreferenceHandler(key); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.ui/"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| String lastSegment = key.lastSegment(); |
| if (lastSegment.startsWith("cleanup.")) |
| { |
| return new PreferenceHandler(key) |
| { |
| @Override |
| public boolean isIgnored() |
| { |
| return true; |
| } |
| }; |
| } |
| |
| return new PreferenceHandler(key); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.formatterprofiles"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "profile", new String[] { "name" }, null); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.ui/formatter_profile"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new JDTProfileChoicePreferenceHandler(key, "formatter"); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.cleanupprofiles"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "profile", new String[] { "name" }, null); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.ui/cleanup_profile"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new JDTProfileChoicePreferenceHandler(key, "cleanup"); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.team.core/file_types"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new TeamFileModePreferenceHandler(key); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.team.core/cvs_mode_for_file_without_extensions"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new TeamFileModePreferenceHandler(key); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_templates"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "template", new String[] { "id" }, null); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui.text.custom_code_templates"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "template", new String[] { "context", "description", "name" }, null); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.ant.ui/org.eclipse.ant.ui.customtemplates"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "template", new String[] { "context", "description", "name" }, new String[] { "id" }); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.core.variables/org.eclipse.core.variables.valueVariables"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "valueVariable", new String[] { "name" }, null); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.m2e.editor.xml/org.eclipse.m2e.editor.xml.templates"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "template", new String[] { "context", "description", "name" }, new String[] { "id" }); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.cdt.ui/org.eclipse.cdt.ui.formatterprofiles"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new XMLPreferenceHandler(key, "profile", new String[] { "name" }, null); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.cdt.ui/formatter_profile"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| return new CDTProfileChoicePreferenceHandler(key); |
| } |
| }); |
| |
| registry.put(URI.createURI("//instance/org.eclipse.cdt.core/"), new Factory() |
| { |
| public PreferenceHandler create(URI key) |
| { |
| String lastSegment = key.lastSegment(); |
| if (lastSegment.startsWith("org.eclipse.cdt.core.formatter.")) |
| { |
| return new IgnoredPreferenceHandler(key); |
| } |
| |
| return new PreferenceHandler(key); |
| } |
| }); |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public interface Factory |
| { |
| public PreferenceHandler create(URI key); |
| |
| /** |
| * @author Ed Merks |
| */ |
| public interface Registry |
| { |
| public Registry INSTANCE = new PreferenceHandlerFactoryRegistry(); |
| |
| public Factory getFactory(URI key); |
| } |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class IgnoredPreferenceHandler extends PreferenceHandler |
| { |
| public IgnoredPreferenceHandler(URI key) |
| { |
| super(key); |
| } |
| |
| @Override |
| public boolean isIgnored() |
| { |
| return true; |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class ListPreferenceHandler extends PreferenceHandler |
| { |
| protected final Pattern itemPattern; |
| |
| protected final Pattern keyPattern; |
| |
| protected final String separator; |
| |
| protected final Set<String> changedItems = new LinkedHashSet<String>(); |
| |
| protected final Map<String, Item> oldItems = new LinkedHashMap<String, Item>(); |
| |
| protected final Map<String, Item> newItems = new LinkedHashMap<String, Item>(); |
| |
| protected final Map<String, Item> mergedItems = new LinkedHashMap<String, Item>(); |
| |
| private boolean keyCollision; |
| |
| public ListPreferenceHandler(URI key, String itemPattern, String keyPattern, String separator) |
| { |
| super(key); |
| this.itemPattern = Pattern.compile(itemPattern); |
| this.keyPattern = Pattern.compile(keyPattern); |
| this.separator = separator; |
| } |
| |
| @Override |
| protected boolean isExcluded() |
| { |
| return false; |
| } |
| |
| @Override |
| protected boolean isNeeded() |
| { |
| return super.isNeeded() && !keyCollision; |
| } |
| |
| @Override |
| public String merge() |
| { |
| keyCollision = false; |
| changedItems.clear(); |
| oldItems.clear(); |
| newItems.clear(); |
| mergedItems.clear(); |
| |
| oldItems.putAll(getItems(oldValue)); |
| newItems.putAll(getItems(newValue)); |
| if (oldItems.isEmpty()) |
| { |
| changedItems.addAll(newItems.keySet()); |
| mergedItems.putAll(newItems); |
| return newValue; |
| } |
| |
| mergedItems.putAll(oldItems); |
| for (Map.Entry<String, Item> entry : newItems.entrySet()) |
| { |
| String entryKey = entry.getKey(); |
| Item newItem = entry.getValue(); |
| Item oldItem = mergedItems.put(entryKey, newItem); |
| if (oldItem == null || !oldItem.getValue().equals(newItem.getValue())) |
| { |
| changedItems.add(entryKey); |
| } |
| } |
| |
| List<Item> oldItemValues = new ArrayList<Item>(oldItems.values()); |
| StringBuilder result = new StringBuilder(oldItemValues.get(0).getHead()); |
| for (Iterator<Item> it = mergedItems.values().iterator(); it.hasNext();) |
| { |
| Item item = it.next(); |
| result.append(item.getValue()); |
| if (it.hasNext()) |
| { |
| result.append(separator); |
| } |
| } |
| |
| result.append(oldItemValues.get(oldItemValues.size() - 1).getTail()); |
| |
| return result.toString(); |
| } |
| |
| @Override |
| public String delta() |
| { |
| merge(); |
| |
| if (oldItems.isEmpty()) |
| { |
| return newValue; |
| } |
| |
| List<Item> itemValues = new ArrayList<Item>(oldItems.values()); |
| StringBuilder result = new StringBuilder(itemValues.get(0).getHead()); |
| for (Iterator<String> it = changedItems.iterator(); it.hasNext();) |
| { |
| Item item = mergedItems.get(it.next()); |
| result.append(item.getValue()); |
| if (it.hasNext()) |
| { |
| result.append(separator); |
| } |
| } |
| |
| result.append(itemValues.get(itemValues.size() - 1).getTail()); |
| |
| return result.toString(); |
| } |
| |
| private Map<String, Item> getItems(String value) |
| { |
| Map<String, Item> items = new LinkedHashMap<String, Item>(); |
| if (value != null) |
| { |
| for (Matcher matcher = itemPattern.matcher(value); matcher.find();) |
| { |
| String group = matcher.group(1); |
| Matcher keyMatcher = keyPattern.matcher(group); |
| if (keyMatcher.find()) |
| { |
| StringBuilder key = new StringBuilder(); |
| for (int i = 1, count = keyMatcher.groupCount(); i <= count; ++i) |
| { |
| if (i > 1) |
| { |
| key.append("_._"); |
| } |
| |
| key.append(keyMatcher.group(i)); |
| } |
| |
| Item oldItem = items.put(key.toString(), new Item(value, matcher.start(1), matcher.end(1))); |
| if (oldItem != null) |
| { |
| keyCollision = true; |
| } |
| } |
| } |
| } |
| |
| return items; |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static final class Item |
| { |
| private final String value; |
| |
| private final int start; |
| |
| private final int end; |
| |
| public Item(String value, int start, int end) |
| { |
| this.value = value; |
| this.start = start; |
| this.end = end; |
| } |
| |
| public String getValue() |
| { |
| return value.substring(start, end); |
| } |
| |
| public String getHead() |
| { |
| return value.substring(0, start); |
| } |
| |
| public String getTail() |
| { |
| return value.substring(end); |
| } |
| |
| @Override |
| public String toString() |
| { |
| return getValue(); |
| } |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class XMLPreferenceHandler extends ListPreferenceHandler |
| { |
| public XMLPreferenceHandler(URI key, String tag, String[] requiredAttributes, String[] optionalAttributes) |
| { |
| super(key, getItemPattern(tag), getKeyPattern(requiredAttributes, optionalAttributes), "\n"); |
| } |
| |
| private static String getItemPattern(String tag) |
| { |
| return "(?s)(<" + tag + " (?:[^>]*/>|.*?</" + tag + ">))"; |
| } |
| |
| private static String getKeyPattern(String[] requiredAttributes, String[] optionalAttributes) |
| { |
| Set<String> attributes = new TreeSet<String>(Arrays.asList(requiredAttributes)); |
| List<String> optional = optionalAttributes == null ? Collections.<String> emptyList() : Arrays.asList(optionalAttributes); |
| attributes.addAll(optional); |
| |
| StringBuilder result = new StringBuilder(); |
| for (String attribute : attributes) |
| { |
| int length = result.length(); |
| |
| boolean isOptional = optional.contains(attribute); |
| if (isOptional) |
| { |
| result.append("(?:"); |
| } |
| |
| if (length != 0) |
| { |
| result.append("[^>]+"); |
| } |
| |
| result.append(attribute); |
| result.append("=\"([^\"]+)\""); |
| |
| if (isOptional) |
| { |
| result.append(")?"); |
| } |
| } |
| |
| return result.toString(); |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class TeamFileModePreferenceHandler extends ListPreferenceHandler |
| { |
| protected static final Set<String> DEFAULT_NAME_MAPPINGS = new LinkedHashSet<String>(); |
| |
| protected static final Set<String> DEFAULT_EXTENSION_MAPPINGS = new LinkedHashSet<String>(); |
| |
| protected static final Object FILE_CONTENT_MANAGER; |
| |
| protected boolean isExtension; |
| |
| static |
| { |
| Object fileContentManager = null; |
| try |
| { |
| Class<?> teamClass = CommonPlugin.loadClass("org.eclipse.team.core", "org.eclipse.team.core.Team"); |
| fileContentManager = ReflectUtil.invokeMethod("getFileContentManager", teamClass); |
| Object[] defaultNameMappings = (Object[])ReflectUtil.invokeMethod("getDefaultNameMappings", fileContentManager); |
| populateMappings(DEFAULT_NAME_MAPPINGS, defaultNameMappings); |
| Object[] defaultExtensionMappings = (Object[])ReflectUtil.invokeMethod("getDefaultExtensionMappings", fileContentManager); |
| populateMappings(DEFAULT_EXTENSION_MAPPINGS, defaultExtensionMappings); |
| } |
| catch (Throwable throwable) |
| { |
| //$FALL-THROUGH$ |
| } |
| |
| FILE_CONTENT_MANAGER = fileContentManager; |
| } |
| |
| public TeamFileModePreferenceHandler(URI key) |
| { |
| super(key, "(?s)([^\\n]+\\n[0-9]+)", "([^\n]+)", "\n"); |
| isExtension = "file_types".equals(key.lastSegment()); |
| } |
| |
| @Override |
| public String delta() |
| { |
| if (StringUtil.isEmpty(oldValue)) |
| { |
| StringBuilder result = new StringBuilder(super.delta()); |
| for (String mapping : isExtension ? DEFAULT_EXTENSION_MAPPINGS : DEFAULT_NAME_MAPPINGS) |
| { |
| int index = result.indexOf(mapping); |
| if (index == 0 || index > 0 && result.charAt(index - 1) == '\n') |
| { |
| result.delete(index, index + mapping.length()); |
| } |
| } |
| |
| return result.toString(); |
| } |
| |
| return super.delta(); |
| } |
| |
| @Override |
| public void apply(SetupTaskContext context) |
| { |
| if (FILE_CONTENT_MANAGER != null) |
| { |
| int size = changedItems.size(); |
| String[] names = new String[size]; |
| int[] types = new int[size]; |
| int index = 0; |
| for (String changedItem : changedItems) |
| { |
| names[index] = changedItem; |
| String value = mergedItems.get(changedItem).getValue(); |
| int offset = value.indexOf('\n'); |
| types[index] = Integer.parseInt(value.substring(offset + 1)); |
| ++index; |
| } |
| |
| ReflectUtil.invokeMethod( |
| ReflectUtil.getMethod(FILE_CONTENT_MANAGER.getClass(), isExtension ? "addExtensionMappings" : "addNameMappings", String[].class, int[].class), |
| FILE_CONTENT_MANAGER, names, types); |
| } |
| } |
| |
| private static void populateMappings(Set<String> target, Object[] mappings) |
| { |
| for (Object mapping : mappings) |
| { |
| Object string = ReflectUtil.invokeMethod("getString", mapping); |
| int type = (Integer)ReflectUtil.invokeMethod("getType", mapping); |
| target.add(string + "\n" + type + "\n"); |
| } |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class ContentTypeFileExtensionPreferenceHandler extends ListPreferenceHandler |
| { |
| private final int type; |
| |
| public ContentTypeFileExtensionPreferenceHandler(URI key) |
| { |
| super(key, "([^,]+)", "([^,]+)", ","); |
| type = "file-extensions".equals(key.lastSegment()) ? IContentType.FILE_EXTENSION_SPEC : IContentType.FILE_NAME_SPEC; |
| } |
| |
| @Override |
| public void apply(SetupTaskContext context) |
| { |
| String contentTypeName = key.segment(key.segmentCount() - 2); |
| IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeName); |
| if (contentType != null) |
| { |
| for (String key : changedItems) |
| { |
| try |
| { |
| contentType.addFileSpec(key, type); |
| } |
| catch (CoreException ex) |
| { |
| context.log(ex); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class ContentTypeCharsetPreferenceHandler extends PreferenceHandler |
| { |
| public ContentTypeCharsetPreferenceHandler(URI key) |
| { |
| super(key); |
| } |
| |
| @Override |
| public void apply(SetupTaskContext context) |
| { |
| String contentTypeName = key.segment(key.segmentCount() - 2); |
| IContentType contentType = Platform.getContentTypeManager().getContentType(contentTypeName); |
| if (contentType != null) |
| { |
| try |
| { |
| contentType.setDefaultCharset(newValue); |
| } |
| catch (CoreException ex) |
| { |
| context.log(ex); |
| } |
| } |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static abstract class ProfileChoicePreferenceHandler extends PreferenceHandler |
| { |
| private static final Pattern SETTING_PATTERN = Pattern.compile("<setting id=\"([^\"]+)\" value=\"([^\"]+)\""); |
| |
| public ProfileChoicePreferenceHandler(URI key) |
| { |
| super(key); |
| } |
| |
| @Override |
| public int getPriority() |
| { |
| return PRIORITY_EARLY + 1; |
| } |
| |
| protected abstract PreferenceProperty getProfilesPreferenceProperty(); |
| |
| protected abstract PreferenceProperty getKeyPreferenceProperty(String propertyKey); |
| |
| @Override |
| public void apply(SetupTaskContext context) |
| { |
| PreferenceProperty profiles = getProfilesPreferenceProperty(); |
| Pattern pattern = Pattern.compile("(?s)(<profile[^\n]*name=\"" + newValue.substring(1) + "\".*?</profile>)"); |
| String value = profiles.get(null); |
| if (value != null) |
| { |
| Matcher matcher = pattern.matcher(value); |
| if (matcher.find()) |
| { |
| String profile = matcher.group(1); |
| for (Matcher settingMatcher = SETTING_PATTERN.matcher(profile); settingMatcher.find();) |
| { |
| String propertyKey = settingMatcher.group(1); |
| String propertyValue = settingMatcher.group(2); |
| PreferenceProperty property = getKeyPreferenceProperty(propertyKey); |
| property.set(propertyValue); |
| } |
| } |
| } |
| } |
| } |
| |
| public static class JDTProfileChoicePreferenceHandler extends ProfileChoicePreferenceHandler |
| { |
| private String profileType; |
| |
| public JDTProfileChoicePreferenceHandler(URI key, String profileType) |
| { |
| super(key); |
| this.profileType = profileType; |
| } |
| |
| @Override |
| protected PreferenceProperty getProfilesPreferenceProperty() |
| { |
| return new PreferencesUtil.PreferenceProperty("/instance/org.eclipse.jdt.ui/org.eclipse.jdt.ui." + profileType + "profiles"); |
| } |
| |
| @Override |
| protected PreferenceProperty getKeyPreferenceProperty(String propertyKey) |
| { |
| return new PreferencesUtil.PreferenceProperty("/instance/org.eclipse.jdt.core/" + propertyKey); |
| } |
| } |
| |
| public static class CDTProfileChoicePreferenceHandler extends ProfileChoicePreferenceHandler |
| { |
| public CDTProfileChoicePreferenceHandler(URI key) |
| { |
| super(key); |
| } |
| |
| @Override |
| protected PreferenceProperty getProfilesPreferenceProperty() |
| { |
| return new PreferencesUtil.PreferenceProperty("/instance/org.eclipse.cdt.ui/org.eclipse.cdt.ui.formatterprofiles"); |
| } |
| |
| @Override |
| protected PreferenceProperty getKeyPreferenceProperty(String propertyKey) |
| { |
| return new PreferencesUtil.PreferenceProperty("/instance/org.eclipse.cdt.core/" + propertyKey); |
| } |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| public static class PreferenceHandlerFactoryRegistry extends BasicEMap<URI, PreferenceHandler.Factory> implements PreferenceHandler.Factory.Registry |
| { |
| private static final URI ROOT_PREFIX = URI.createURI("//"); |
| |
| private static final long serialVersionUID = 1L; |
| |
| protected BasicEList<List<Map.Entry<URI, PreferenceHandler.Factory>>> prefixMaps; |
| |
| public PreferenceHandlerFactoryRegistry() |
| { |
| super(); |
| } |
| |
| @Override |
| protected Entry<URI, PreferenceHandler.Factory> newEntry(int hash, URI key, PreferenceHandler.Factory value) |
| { |
| validateKey(key); |
| validateValue(value); |
| return new MappingEntryImpl(hash, key, value); |
| } |
| |
| /** |
| * @author Ed Merks |
| */ |
| protected class MappingEntryImpl extends EntryImpl |
| { |
| public boolean isPrefixMapEntry; |
| |
| public MappingEntryImpl(int hash, URI key, PreferenceHandler.Factory value) |
| { |
| super(hash, key, value); |
| determineEntryType(); |
| } |
| |
| public void determineEntryType() |
| { |
| isPrefixMapEntry = "".equals(key.authority()) ? key.segmentCount() == 0 |
| : key.segmentCount() == 0 ? key.hasAbsolutePath() : key.hasTrailingPathSeparator(); |
| } |
| } |
| |
| public PreferenceHandler.Factory getFactory(URI uri) |
| { |
| PreferenceHandler.Factory result = get(uri); |
| if (result == null && prefixMaps != null && uri != null) |
| { |
| for (int i = Math.min(prefixMaps.size() - 1, uri.segmentCount()); i >= 0; --i) |
| { |
| List<Map.Entry<URI, PreferenceHandler.Factory>> prefixes = prefixMaps.get(i); |
| LOOP: for (int j = prefixes.size() - 1; j >= 0; --j) |
| { |
| Map.Entry<URI, PreferenceHandler.Factory> entry = prefixes.get(j); |
| URI key = entry.getKey(); |
| if (ROOT_PREFIX.equals(key)) |
| { |
| return entry.getValue(); |
| } |
| |
| for (int k = key.segmentCount() - 2; k >= 0; --k) |
| { |
| if (!key.segment(k).equals(uri.segment(k))) |
| { |
| continue LOOP; |
| } |
| } |
| |
| if (key.authority().equals(uri.authority())) |
| { |
| return entry.getValue(); |
| } |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| @Override |
| protected void validateKey(URI key) |
| { |
| if (key == null) |
| { |
| throw new RuntimeException("Key may not be null"); |
| } |
| |
| if (!key.isHierarchical()) |
| { |
| throw new RuntimeException("Key is not hierarchical " + key); |
| } |
| |
| if (key.authority() == null) |
| { |
| throw new RuntimeException("Key has no authority " + key); |
| } |
| |
| if (key.scheme() != null) |
| { |
| throw new RuntimeException("Key should not have a scheme " + key); |
| } |
| } |
| |
| @Override |
| protected void validateValue(Factory value) |
| { |
| if (value == null) |
| { |
| throw new RuntimeException("Value may not be null"); |
| } |
| } |
| |
| @Override |
| protected void didAdd(Entry<URI, PreferenceHandler.Factory> entry) |
| { |
| if (((MappingEntryImpl)entry).isPrefixMapEntry) |
| { |
| int length = entry.getKey().segmentCount(); |
| if (prefixMaps == null) |
| { |
| prefixMaps = new BasicEList<List<Map.Entry<URI, PreferenceHandler.Factory>>>(); |
| } |
| |
| for (int i = prefixMaps.size() - 1; i <= length; ++i) |
| { |
| prefixMaps.add(new BasicEList<Map.Entry<URI, PreferenceHandler.Factory>>()); |
| } |
| |
| prefixMaps.get(length).add(entry); |
| } |
| } |
| |
| @Override |
| protected void didModify(Entry<URI, PreferenceHandler.Factory> entry, PreferenceHandler.Factory oldValue) |
| { |
| didRemove(entry); |
| ((MappingEntryImpl)entry).determineEntryType(); |
| didAdd(entry); |
| } |
| |
| @Override |
| protected void didRemove(Entry<URI, PreferenceHandler.Factory> entry) |
| { |
| if (((MappingEntryImpl)entry).isPrefixMapEntry) |
| { |
| int length = entry.getKey().segmentCount(); |
| prefixMaps.get(length).remove(entry); |
| } |
| } |
| |
| @Override |
| protected void didClear(BasicEList<Entry<URI, PreferenceHandler.Factory>>[] oldEntryData) |
| { |
| prefixMaps = null; |
| } |
| } |
| } // PreferenceTaskImpl |