1 package org.simantics.aeri.redmine.core.di;
3 import java.util.HashSet;
7 import org.eclipse.core.runtime.preferences.ConfigurationScope;
8 import org.eclipse.core.runtime.preferences.InstanceScope;
9 import org.eclipse.e4.core.contexts.IContextFunction;
10 import org.eclipse.e4.core.contexts.IEclipseContext;
11 import org.eclipse.emf.common.notify.Notification;
12 import org.eclipse.emf.common.notify.impl.AdapterImpl;
13 import org.eclipse.emf.ecore.EAttribute;
14 import org.eclipse.emf.ecore.EClass;
15 import org.eclipse.emf.ecore.EDataType;
16 import org.eclipse.emf.ecore.EStructuralFeature;
17 import org.eclipse.emf.ecore.util.EcoreUtil;
18 import org.eclipse.epp.logging.aeri.core.SystemControl;
19 import org.eclipse.jface.util.IPropertyChangeListener;
20 import org.eclipse.jface.util.PropertyChangeEvent;
21 import org.eclipse.ui.preferences.ScopedPreferenceStore;
22 import org.simantics.aeri.redmine.core.internal.Activator;
23 import org.simantics.aeri.redmine.core.settings.RedmineAERISettings;
24 import org.simantics.aeri.redmine.core.settings.RedmineAERISettingsFactory;
25 import org.simantics.aeri.redmine.core.settings.RedmineAERISettingsPackage;
27 import com.google.common.base.Joiner;
28 import com.google.common.base.Splitter;
29 import com.google.common.collect.ImmutableSet;
32 * Context function that computes the {@link RedmineAERISettings}.
34 public class RedmineAERISettingsCreationFunction implements IContextFunction {
37 public Object compute(IEclipseContext localContext, String contextKey) {
38 RedmineAERISettings settings = RedmineAERISettingsFactory.eINSTANCE.createRedmineAERISettings();
39 EClass eClass = settings.eClass();
40 ScopedPreferenceStore instanceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.BUNDLE_ID);
41 loadFromPreferences(instanceStore, settings, eClass);
42 registerPreferenceStoreChangeListener(instanceStore, settings, eClass);
43 registerSettingsChangeListener(instanceStore, settings, new HashSet<EAttribute>());
45 // register a listener that sends selected changes to the configuration scope store:
46 // convenience to allow users with different workspaces to reuse the settings
47 ScopedPreferenceStore configurationStore = new ScopedPreferenceStore(ConfigurationScope.INSTANCE, Activator.BUNDLE_ID);
48 registerSettingsChangeListener(configurationStore, settings,
49 ImmutableSet.of(RedmineAERISettingsPackage.eINSTANCE.getRedmineAERISettings_ApiKey()));
51 // set this settings object in the root context. Effectively replaces this context function.
52 IEclipseContext systemContext = SystemControl.getSystemContext();
53 systemContext.set(contextKey, settings);
57 private static void registerSettingsChangeListener(final ScopedPreferenceStore store, final RedmineAERISettings settings,
58 final Set<EAttribute> allowedKeys) {
59 settings.eAdapters().add(new AdapterImpl() {
61 public void notifyChanged(Notification msg) {
62 Object feature = msg.getFeature();
63 if (!(feature instanceof EAttribute)) {
66 EAttribute attr = (EAttribute) feature;
67 EDataType type = attr.getEAttributeType();
68 Object value = msg.getNewValue();
71 String data = EcoreUtil.convertToString(type, value);
73 // if empty all keys are allowed:
74 if (allowedKeys.isEmpty() || allowedKeys.contains(attr)) {
76 // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=494098,
77 // data may be null and null is not valid as value
79 store.setToDefault(attr.getName());
81 store.putValue(attr.getName(), data);
84 } catch (Exception e) {
86 // log(ERROR_SAVE_PREFERENCES_FAILED, e, attr.getName(), data);
93 private static void registerPreferenceStoreChangeListener(final ScopedPreferenceStore store, final RedmineAERISettings settings,
94 final EClass eClass) {
95 store.addPropertyChangeListener(new IPropertyChangeListener() {
98 public void propertyChange(PropertyChangeEvent event) {
99 String property = event.getProperty();
100 EStructuralFeature feature = eClass.getEStructuralFeature(property);
101 if (feature != null && feature instanceof EAttribute) {
102 EAttribute attr = (EAttribute) feature;
103 EDataType type = attr.getEAttributeType();
104 String string = EcoreUtil.convertToString(type, event.getNewValue());
105 Object value = EcoreUtil.createFromString(type, string);
106 settings.eSet(feature, value);
112 private static void loadFromPreferences(final ScopedPreferenceStore store, final RedmineAERISettings settings, final EClass eClass) {
113 for (EAttribute attr : eClass.getEAllAttributes()) {
114 EDataType type = attr.getEAttributeType();
115 String key = attr.getName();
116 if (!store.contains(key)) {
119 String value = store.getString(key);
122 for (String s : convert(value)) {
123 Object data = EcoreUtil.createFromString(type, s);
124 ((List<Object>) settings.eGet(attr)).add(data);
128 Object data = EcoreUtil.createFromString(type, value);
129 settings.eSet(attr, data);
130 } catch (Exception e) {
132 // log(ERROR_FAILED_TO_PARSE_PREFERENCE_VALUE, attr, value);
137 static List<String> convert(String string) {
138 return Splitter.on(';').omitEmptyStrings().trimResults().splitToList(string);
142 static String convert(List<String> strings) {
143 return Joiner.on(';').skipNulls().join(strings);