blob: b85ec0742850b1dc5161ac9ee2f6ae77bc04ebcd [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2006, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.ecommons.preferences.core.util;
import java.util.List;
import java.util.Map;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.collections.ImSet;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.ecommons.preferences.core.Preference;
import org.eclipse.statet.ecommons.preferences.core.PreferenceAccess;
import org.eclipse.statet.ecommons.preferences.core.PreferenceSetService;
import org.eclipse.statet.internal.ecommons.preferences.core.ECommonsPreferencesCorePlugin;
@NonNullByDefault
public final class PreferenceUtils {
private static class DefaultImpl implements PreferenceAccess {
private final ImList<IScopeContext> contexts;
private DefaultImpl(final ImList<IScopeContext> contexts) {
this.contexts= contexts;
}
@Override
public ImList<IScopeContext> getPreferenceContexts() {
return this.contexts;
}
@Override
public <T> T getPreferenceValue(final Preference<T> pref) {
return PreferenceUtils.getPrefValue(this.contexts, pref);
}
@Override
public void addPreferenceNodeListener(final String nodeQualifier, final IPreferenceChangeListener listener) {
for (int i= 0; i < this.contexts.size(); i++) {
final IScopeContext context= this.contexts.get(i);
if (context instanceof DefaultScope) {
continue;
}
final IEclipsePreferences node= context.getNode(nodeQualifier);
if (node != null) {
node.addPreferenceChangeListener(listener);
}
}
}
@Override
public void removePreferenceNodeListener(final String nodeQualifier, final IPreferenceChangeListener listener) {
for (int i= 0; i < this.contexts.size(); i++) {
final IScopeContext context= this.contexts.get(i);
if (context instanceof DefaultScope) {
continue;
}
final IEclipsePreferences node= context.getNode(nodeQualifier);
if (node != null) {
node.removePreferenceChangeListener(listener);
}
}
}
@Override
public void addPreferenceSetListener(final PreferenceSetService.ChangeListener listener,
final ImSet<String> qualifiers) {
getPreferenceSetService().addChangeListener(listener,
getPreferenceContexts(), qualifiers );
}
@Override
public void removePreferenceSetListener(final PreferenceSetService.ChangeListener listener) {
final PreferenceSetService service= getPreferenceSetService();
if (service != null) {
service.removeChangeListener(listener);
}
}
}
private static class MapImpl implements PreferenceAccess {
private final Map<Preference<?>, Object> preferencesMap;
MapImpl(final Map<Preference<?>, Object> preferencesMap) {
this.preferencesMap= preferencesMap;
}
@Override
public ImList<IScopeContext> getPreferenceContexts() {
return ImCollections.emptyList();
}
@Override
@SuppressWarnings("unchecked")
public <T> T getPreferenceValue(final Preference<T> pref) {
return (T) this.preferencesMap.get(pref);
}
/**
* Not (yet) supported
*/
@Override
public void addPreferenceNodeListener(final String nodeQualifier, final IPreferenceChangeListener listener) {
throw new UnsupportedOperationException();
}
/**
* Not (yet) supported
*/
@Override
public void removePreferenceNodeListener(final String nodeQualifier, final IPreferenceChangeListener listener) {
throw new UnsupportedOperationException();
}
/**
* Not (yet) supported
*/
@Override
public void addPreferenceSetListener(final PreferenceSetService.ChangeListener listener,
final ImSet<String> qualifiers) {
throw new UnsupportedOperationException();
}
/**
* Not (yet) supported
*/
@Override
public void removePreferenceSetListener(final PreferenceSetService.ChangeListener listener) {
throw new UnsupportedOperationException();
}
}
private final static DefaultImpl DEFAULT_PREFS= new DefaultImpl(ImCollections.newList(
DefaultScope.INSTANCE ));
private final static DefaultImpl INSTANCE_PREFS= new DefaultImpl(ImCollections.newList(
InstanceScope.INSTANCE,
DefaultScope.INSTANCE ));
public final static PreferenceAccess getInstancePrefs() {
return INSTANCE_PREFS;
}
public final static PreferenceAccess getDefaultPrefs() {
return DEFAULT_PREFS;
}
public static PreferenceAccess createAccess(final Map<Preference<?>, Object> preferencesMap) {
return new MapImpl(preferencesMap);
}
public static PreferenceAccess createAccess(final List<IScopeContext> contexts) {
return new DefaultImpl(ImCollections.toList(contexts));
}
public static final int FLUSH_SYNC= 1 << 0;
public static final int FLUSH_ASYNC= 1 << 1;
public static <T> T getPrefValue(final List<IScopeContext> contexts, final Preference<T> pref) {
String storeValue= null;
for (int i= 0; i < contexts.size() && storeValue == null; i++) {
try {
storeValue= contexts.get(i).getNode(pref.getQualifier()).get(pref.getKey(), null);
}
catch (final IllegalStateException e) {
}
}
return pref.store2Usage(storeValue);
}
public static <T> T getPrefValue(final IScopeContext context, final Preference<T> pref) {
final IEclipsePreferences node= context.getNode(pref.getQualifier());
return getPrefValue(node, pref);
}
public static <T> T getPrefValue(final IEclipsePreferences node, final Preference<T> pref) {
final String storeValue= node.get(pref.getKey(), (String) null);
return pref.store2Usage(storeValue);
}
public static <T> void setPrefValue(final IScopeContext context,
final Preference<T> pref, final T value) {
final IEclipsePreferences node= context.getNode(pref.getQualifier());
setPrefValue(node, pref, value);
}
public static <T> void setPrefValue(final IScopeContext context,
final Preference<T> pref, final T value, final int flags) {
final IEclipsePreferences node= context.getNode(pref.getQualifier());
setPrefValue(node, pref, value);
if ((flags & FLUSH_SYNC) != 0) {
flush(node);
}
else if ((flags & FLUSH_ASYNC) != 0) {
final Job job= new Job("Save Preferences") {
@Override
protected IStatus run(final IProgressMonitor monitor) {
flush(node);
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.setUser(false);
job.setPriority(Job.SHORT);
job.schedule();
}
}
private static void flush(final Preferences node) {
try {
node.flush();
}
catch (final BackingStoreException e) {
ECommonsPreferencesCorePlugin.log(new Status(IStatus.ERROR,
ECommonsPreferencesCorePlugin.BUNDLE_ID,
"An error occurred when saving preferences.", //$NON-NLS-1$
e ));
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void setPrefValues(final IScopeContext context,
final Map<Preference<?>, Object> preferencesMap) {
for (final Map.Entry<Preference<?>, Object> pref : preferencesMap.entrySet()) {
setPrefValue(context, (Preference) pref.getKey(), pref.getValue());
}
}
public static <T> void setPrefValue(final IEclipsePreferences node,
final Preference<T> pref, final T value) {
final String storeValue;
if (value == null
|| (storeValue= pref.usage2Store(value)) == null) {
node.remove(pref.getKey());
return;
}
node.put(pref.getKey(), storeValue);
}
public static PreferenceSetService getPreferenceSetService() {
// Adapt this if used in other context
final ECommonsPreferencesCorePlugin plugin= ECommonsPreferencesCorePlugin.getInstance();
if (plugin != null) {
return plugin.getPreferenceSetService();
}
return null;
}
}