]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.aeri.ui.redmine.core/src/org/simantics/aeri/redmine/core/di/RedmineAERISettingsCreationFunction.java
Experiment around with AERI in Simantics Products
[simantics/platform.git] / bundles / org.simantics.aeri.ui.redmine.core / src / org / simantics / aeri / redmine / core / di / RedmineAERISettingsCreationFunction.java
diff --git a/bundles/org.simantics.aeri.ui.redmine.core/src/org/simantics/aeri/redmine/core/di/RedmineAERISettingsCreationFunction.java b/bundles/org.simantics.aeri.ui.redmine.core/src/org/simantics/aeri/redmine/core/di/RedmineAERISettingsCreationFunction.java
new file mode 100644 (file)
index 0000000..a1cd85f
--- /dev/null
@@ -0,0 +1,145 @@
+package org.simantics.aeri.redmine.core.di;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.preferences.ConfigurationScope;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.e4.core.contexts.IContextFunction;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.epp.logging.aeri.core.SystemControl;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
+import org.simantics.aeri.redmine.core.internal.Activator;
+import org.simantics.aeri.redmine.core.settings.RedmineAERISettings;
+import org.simantics.aeri.redmine.core.settings.RedmineAERISettingsFactory;
+import org.simantics.aeri.redmine.core.settings.RedmineAERISettingsPackage;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Context function that computes the {@link RedmineAERISettings}.
+ */
+public class RedmineAERISettingsCreationFunction implements IContextFunction {
+
+    @Override
+    public Object compute(IEclipseContext localContext, String contextKey) {
+        RedmineAERISettings settings = RedmineAERISettingsFactory.eINSTANCE.createRedmineAERISettings();
+        EClass eClass = settings.eClass();
+        ScopedPreferenceStore instanceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE, Activator.BUNDLE_ID);
+        loadFromPreferences(instanceStore, settings, eClass);
+        registerPreferenceStoreChangeListener(instanceStore, settings, eClass);
+        registerSettingsChangeListener(instanceStore, settings, new HashSet<EAttribute>());
+
+        // register a listener that sends selected changes to the configuration scope store:
+        // convenience to allow users with different workspaces to reuse the settings
+        ScopedPreferenceStore configurationStore = new ScopedPreferenceStore(ConfigurationScope.INSTANCE, Activator.BUNDLE_ID);
+        registerSettingsChangeListener(configurationStore, settings,
+                ImmutableSet.of(RedmineAERISettingsPackage.eINSTANCE.getRedmineAERISettings_ApiKey()));
+
+        // set this settings object in the root context. Effectively replaces this context function.
+        IEclipseContext systemContext = SystemControl.getSystemContext();
+        systemContext.set(contextKey, settings);
+        return settings;
+    }
+
+    private static void registerSettingsChangeListener(final ScopedPreferenceStore store, final RedmineAERISettings settings,
+            final Set<EAttribute> allowedKeys) {
+        settings.eAdapters().add(new AdapterImpl() {
+            @Override
+            public void notifyChanged(Notification msg) {
+                Object feature = msg.getFeature();
+                if (!(feature instanceof EAttribute)) {
+                    return;
+                }
+                EAttribute attr = (EAttribute) feature;
+                EDataType type = attr.getEAttributeType();
+                Object value = msg.getNewValue();
+
+                // @Nullable
+                String data = EcoreUtil.convertToString(type, value);
+
+                // if empty all keys are allowed:
+                if (allowedKeys.isEmpty() || allowedKeys.contains(attr)) {
+                    try {
+                        // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=494098,
+                        // data may be null and null is not valid as value
+                        if (data == null) {
+                            store.setToDefault(attr.getName());
+                        } else {
+                            store.putValue(attr.getName(), data);
+                        }
+                        store.save();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+//                        log(ERROR_SAVE_PREFERENCES_FAILED, e, attr.getName(), data);
+                    }
+                }
+            }
+        });
+    }
+
+    private static void registerPreferenceStoreChangeListener(final ScopedPreferenceStore store, final RedmineAERISettings settings,
+            final EClass eClass) {
+        store.addPropertyChangeListener(new IPropertyChangeListener() {
+
+            @Override
+            public void propertyChange(PropertyChangeEvent event) {
+                String property = event.getProperty();
+                EStructuralFeature feature = eClass.getEStructuralFeature(property);
+                if (feature != null && feature instanceof EAttribute) {
+                    EAttribute attr = (EAttribute) feature;
+                    EDataType type = attr.getEAttributeType();
+                    String string = EcoreUtil.convertToString(type, event.getNewValue());
+                    Object value = EcoreUtil.createFromString(type, string);
+                    settings.eSet(feature, value);
+                }
+            }
+        });
+    }
+
+    private static void loadFromPreferences(final ScopedPreferenceStore store, final RedmineAERISettings settings, final EClass eClass) {
+        for (EAttribute attr : eClass.getEAllAttributes()) {
+            EDataType type = attr.getEAttributeType();
+            String key = attr.getName();
+            if (!store.contains(key)) {
+                continue;
+            }
+            String value = store.getString(key);
+            try {
+                if (attr.isMany()) {
+                    for (String s : convert(value)) {
+                        Object data = EcoreUtil.createFromString(type, s);
+                        ((List<Object>) settings.eGet(attr)).add(data);
+                    }
+                    continue;
+                }
+                Object data = EcoreUtil.createFromString(type, value);
+                settings.eSet(attr, data);
+            } catch (Exception e) {
+                e.printStackTrace();
+//                log(ERROR_FAILED_TO_PARSE_PREFERENCE_VALUE, attr, value);
+            }
+        }
+    }
+
+    static List<String> convert(String string) {
+        return Splitter.on(';').omitEmptyStrings().trimResults().splitToList(string);
+
+    }
+
+    static String convert(List<String> strings) {
+        return Joiner.on(';').skipNulls().join(strings);
+    }
+}