diff options
author | Christian W. Damus | 2017-12-23 21:18:00 +0000 |
---|---|---|
committer | Christian W. Damus | 2017-12-23 22:08:53 +0000 |
commit | b8f00d122a3f8a6bd94ea8fee8058572e074df89 (patch) | |
tree | 9a3528986572a25548816af5a4f71c23f38a2805 /plugins/infra/internationalization | |
parent | 8ab94c0f6fbacc843b2fc6dc473f5274d12d70bc (diff) | |
download | org.eclipse.papyrus-b8f00d122a3f8a6bd94ea8fee8058572e074df89.tar.gz org.eclipse.papyrus-b8f00d122a3f8a6bd94ea8fee8058572e074df89.tar.xz org.eclipse.papyrus-b8f00d122a3f8a6bd94ea8fee8058572e074df89.zip |
Bug 528343: [I18N] Preference checking overhead for models that don't use i18n
Fix test failures on build machine that is configured for en_US locale.
Also fix new listener API for preference changes that didn't account for
changes applied directly to the preference store (some code does this).
(cherry-picked from streams/3.0-maintenance)
https://bugs.eclipse.org/bugs/show_bug.cgi?id=528343
Change-Id: I7cbe89117bb8cd410ec871dacce78e65937b6880
(cherry picked from commit 791896186a78d125dd13fb1330c65f0067190599)
Diffstat (limited to 'plugins/infra/internationalization')
4 files changed, 507 insertions, 82 deletions
diff --git a/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/Activator.java b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/Activator.java index 40a3d627b31..94f0d662dc0 100644 --- a/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/Activator.java +++ b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/Activator.java @@ -14,18 +14,10 @@ package org.eclipse.papyrus.infra.internationalization.common; -import java.util.HashMap; -import java.util.Map; - import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.preferences.IScopeContext; -import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.papyrus.infra.core.log.LogHelper; -import org.eclipse.papyrus.infra.core.resource.PapyrusProjectScope; -import org.eclipse.papyrus.infra.ui.preferences.PapyrusScopedPreferenceStore; import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.eclipse.ui.preferences.ScopedPreferenceStore; import org.osgi.framework.BundleContext; /** @@ -37,11 +29,11 @@ public class Activator extends AbstractUIPlugin { * The plug-in ID. */ public static final String PLUGIN_ID = "org.eclipse.papyrus.infra.internationalization.common"; //$NON-NLS-1$ - + /** * The internationalization preference node label. */ - public static final String INTERNATIONALIZATION_NODE_LABEL = "internationalization"; //$NON-NLS-1$ + public static final String INTERNATIONALIZATION_NODE_LABEL = PreferenceStoreManager.INTERNATIONALIZATION_NODE_LABEL; /** * The shared instance. @@ -52,42 +44,34 @@ public class Activator extends AbstractUIPlugin { * The log helper. */ public static LogHelper log; - - /** - * Storage for preferences, per scope. - */ - private Map<IScopeContext, IPreferenceStore> preferencesStore; + + private PreferenceStoreManager preferenceStores; /** - * The constructor + * The constructor. */ public Activator() { - preferencesStore = new HashMap<>(); + super(); } - /** - * {@inheritDoc} - * - * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) - */ @Override public void start(final BundleContext context) throws Exception { super.start(context); - plugin = this; + log = new LogHelper(this); + preferenceStores = new PreferenceStoreManager(log); + plugin = this; } - /** - * {@inheritDoc} - * - * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) - */ @Override public void stop(final BundleContext context) throws Exception { + preferenceStores.dispose(); + preferenceStores = null; + plugin = null; super.stop(context); } - + /** * Get the preference store and create it if necessary. * @@ -99,15 +83,8 @@ public class Activator extends AbstractUIPlugin { */ public IPreferenceStore getInternationalizationPreferenceStore(final IProject project, final String papyrusProjectName) { - - final IScopeContext scope = new PapyrusProjectScope(project, papyrusProjectName); - IPreferenceStore result = preferencesStore.get(scope); - if (null == result) { - result = new PapyrusScopedPreferenceStore(scope, INTERNATIONALIZATION_NODE_LABEL); - preferencesStore.put(scope, result); - } - - return result; + + return preferenceStores.getInternationalizationPreferenceStore(project, papyrusProjectName); } /** @@ -117,16 +94,7 @@ public class Activator extends AbstractUIPlugin { * @return The preference store. */ public IPreferenceStore getInternationalizationPreferenceStore() { - IScopeContext scope = InstanceScope.INSTANCE; - IPreferenceStore result = preferencesStore.get(scope); - - if (result == null) { - // Create the preference store lazily. - result = new ScopedPreferenceStore(scope, getBundle().getSymbolicName()); - preferencesStore.put(scope, result); - } - - return result; + return preferenceStores.getInternationalizationPreferenceStore(); } /** @@ -137,4 +105,35 @@ public class Activator extends AbstractUIPlugin { public static Activator getDefault() { return plugin; } + + /** + * Add a listener for events in the preference store management cycle. + * Has no effect if the listener is already added. If, at the + * time of this call, there are already preference stores in existence, + * the {@code listener} will be + * {@link IPreferenceStoreListener#preferenceStoreCreated(IProject, String, IPreferenceStore) informed} + * belatedly of their creation. + * + * @param listener + * a listener to add + * + * @noreference This method is not intended to be referenced by clients. + */ + public void addPreferenceStoreListener(IPreferenceStoreListener listener) { + preferenceStores.addPreferenceStoreListener(listener); + } + + /** + * Remove a listener for events in the preference store management cycle. + * Has no effect if the listener is not (still) registered. + * + * @param listener + * a listener to remove + * + * @noreference This method is not intended to be referenced by clients. + */ + public void removePreferenceStoreListener(IPreferenceStoreListener listener) { + preferenceStores.removePreferenceStoreListener(listener); + } + } diff --git a/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/IPreferenceStoreListener.java b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/IPreferenceStoreListener.java new file mode 100644 index 00000000000..abc4c70ca71 --- /dev/null +++ b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/IPreferenceStoreListener.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2017 Christian W. Damus 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: + * Christian W. Damus - initial API and implementation + *******************************************************************************/ +package org.eclipse.papyrus.infra.internationalization.common; + +import java.util.EventListener; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.preference.IPreferenceStore; + +/** + * A listener to which the {@link Activator} can call back on creation + * and disposal of project-scoped {@link IPreferenceStore}s for internationalization. + * + * @author Christian W. Damus + * + * @noreference This interface is not intended to be referenced by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ +public interface IPreferenceStoreListener extends EventListener { + + /** + * Notifies me that a preference {@code store} was created. + * + * @param project + * the project for which a preference store was created + * @param papyrusProject + * the Papyrus project (name of the model within the {@code project}) + * for which it was created + * @param store + * the store that was created + */ + void preferenceStoreCreated(IProject project, String papyrusProject, IPreferenceStore store); + + /** + * Notifies me that a preference {@code store} was disposed. + * + * @param project + * the project for which a preference store was disposed + * @param papyrusProject + * the Papyrus project (name of the model within the {@code project}) + * @param store + * the store that was disposed + */ + void preferenceStoreDisposed(IProject project, String papyrusProject, IPreferenceStore store); +} diff --git a/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/PreferenceStoreManager.java b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/PreferenceStoreManager.java new file mode 100644 index 00000000000..43516aecf79 --- /dev/null +++ b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/PreferenceStoreManager.java @@ -0,0 +1,269 @@ +/***************************************************************************** + * Copyright (c) 2016, 2017 CEA LIST, Christian W. Damus, 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: + * Nicolas FAUVERGUE (ALL4TEC) nicolas.fauvergue@all4tec.net - Initial API and implementation + * Christian W. Damus - bug 528343 + * + *****************************************************************************/ + +package org.eclipse.papyrus.infra.internationalization.common; + +import static java.util.Collections.singleton; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.preferences.IScopeContext; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.papyrus.infra.core.log.LogHelper; +import org.eclipse.papyrus.infra.core.resource.PapyrusProjectScope; +import org.eclipse.papyrus.infra.ui.preferences.PapyrusScopedPreferenceStore; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.eclipse.ui.preferences.ScopedPreferenceStore; + +/** + * Preference store manager with support for lifecycle listeners. + */ +class PreferenceStoreManager extends AbstractUIPlugin { + /** + * The internationalization preference node label. + */ + static final String INTERNATIONALIZATION_NODE_LABEL = "internationalization"; //$NON-NLS-1$ + + + /** + * Storage for preferences, per scope. + */ + private final Map<ScopeKey, IPreferenceStore> preferenceStores = new HashMap<>(); + + private final CopyOnWriteArrayList<IPreferenceStoreListener> preferenceStoreListeners = new CopyOnWriteArrayList<>(); + + private final LogHelper log; + + /** + * Initializes me with my log helper. + * + * @param log + * my log helper + */ + PreferenceStoreManager(LogHelper log) { + super(); + + this.log = log; + } + + public void dispose() { + disposePreferenceStores(); + preferenceStoreListeners.clear(); + } + + /** + * Get the preference store and create it if necessary. + * + * @param project + * The current project + * @param papyrusProjectName + * The current papyrus project name. + * @return The preference store. + */ + public IPreferenceStore getInternationalizationPreferenceStore(final IProject project, + final String papyrusProjectName) { + + ScopeKey key = new ScopeKey(project, papyrusProjectName); + IPreferenceStore result = preferenceStores.get(key); + if (null == result) { + final IScopeContext scope = new PapyrusProjectScope(project, papyrusProjectName); + result = new PapyrusScopedPreferenceStore(scope, INTERNATIONALIZATION_NODE_LABEL); + preferenceStores.put(new ScopeKey(project, papyrusProjectName), result); + created(project, papyrusProjectName, result); + } + + return result; + } + + /** + * Get the first preference store if existing, else a scoped preference + * store must be created and added to the list of preferences store. + * + * @return The preference store. + */ + public IPreferenceStore getInternationalizationPreferenceStore() { + IPreferenceStore result = preferenceStores.get(ScopeKey.INSTANCE_SCOPE); + + if (result == null) { + // Create the preference store lazily. + IScopeContext scope = InstanceScope.INSTANCE; + result = new ScopedPreferenceStore(scope, getBundle().getSymbolicName()); + preferenceStores.put(ScopeKey.INSTANCE_SCOPE, result); + } + + return result; + } + + /** + * Add a listener for events in the preference store management cycle. + * Has no effect if the listener is already added. If, at the + * time of this call, there are already preference stores in existence, + * the {@code listener} will be + * {@link IPreferenceStoreListener#preferenceStoreCreated(IProject, String, IPreferenceStore) informed} + * belatedly of their creation. + * + * @param listener + * a listener to add + */ + void addPreferenceStoreListener(IPreferenceStoreListener listener) { + if (preferenceStoreListeners.addIfAbsent(listener)) { + added(listener); + } + } + + /** + * Remove a listener for events in the preference store management cycle. + * Has no effect if the listener is not (still) registered. + * + * @param listener + * a listener to remove + */ + void removePreferenceStoreListener(IPreferenceStoreListener listener) { + preferenceStoreListeners.remove(listener); + } + + private void added(IPreferenceStoreListener listener) { + if (hasProjectPreferences()) { + for (Map.Entry<ScopeKey, IPreferenceStore> next : preferenceStores.entrySet()) { + ScopeKey key = next.getKey(); + if (key.isProjectScope()) { + try { + listener.preferenceStoreCreated(key.getProject(), key.getPapyrusProject(), next.getValue()); + } catch (Exception e) { + log.error("Uncaught exception in preference store listener.", e); + } + } + } + } + } + + private void created(IProject project, String papyrusProject, IPreferenceStore store) { + // Notify listeners + if (!preferenceStoreListeners.isEmpty()) { + for (IPreferenceStoreListener next : preferenceStoreListeners) { + try { + next.preferenceStoreCreated(project, papyrusProject, store); + } catch (Exception e) { + log.error("Uncaught exception in preference store listener.", e); + } + } + } + } + + private boolean hasProjectPreferences() { + return !preferenceStores.isEmpty() + && !preferenceStores.keySet().equals(singleton(ScopeKey.INSTANCE_SCOPE)); + } + + private void disposePreferenceStores() { + for (Map.Entry<ScopeKey, IPreferenceStore> next : preferenceStores.entrySet()) { + ScopeKey key = next.getKey(); + if (key.isProjectScope()) { + disposed(key.getProject(), key.getPapyrusProject(), next.getValue()); + } + } + preferenceStores.clear(); + } + + private void disposed(IProject project, String papyrusProject, IPreferenceStore store) { + // Notify listeners + if (!preferenceStoreListeners.isEmpty()) { + for (IPreferenceStoreListener next : preferenceStoreListeners) { + try { + next.preferenceStoreDisposed(project, papyrusProject, store); + } catch (Exception e) { + log.error("Uncaught exception in preference store listener.", e); + } + } + } + } + + // + // Nested types + // + + private static final class ScopeKey { + static final ScopeKey INSTANCE_SCOPE = new ScopeKey(null, null); + + private final IProject project; + private final String papyrusProject; + + ScopeKey(IProject project, String papyrusProject) { + if (project == null && INSTANCE_SCOPE != null) { + throw new NullPointerException("project"); //$NON-NLS-1$ + } + if (papyrusProject == null && project != null) { + throw new NullPointerException("papyrusProject"); //$NON-NLS-1$ + } + + this.project = project; + this.papyrusProject = papyrusProject; + } + + IProject getProject() { + return project; + } + + String getPapyrusProject() { + return papyrusProject; + } + + boolean isProjectScope() { + return project != null; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((papyrusProject == null) ? 0 : papyrusProject.hashCode()); + result = prime * result + ((project == null) ? 0 : project.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ScopeKey other = (ScopeKey) obj; + if (papyrusProject == null) { + if (other.papyrusProject != null) { + return false; + } + } else if (!papyrusProject.equals(other.papyrusProject)) { + return false; + } + if (project == null) { + if (other.project != null) { + return false; + } + } else if (!project.equals(other.project)) { + return false; + } + return true; + } + + } +} diff --git a/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/utils/InternationalizationPreferencesUtils.java b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/utils/InternationalizationPreferencesUtils.java index be71c53b0f6..ee211608671 100644 --- a/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/utils/InternationalizationPreferencesUtils.java +++ b/plugins/infra/internationalization/org.eclipse.papyrus.infra.internationalization.common/src/org/eclipse/papyrus/infra/internationalization/common/utils/InternationalizationPreferencesUtils.java @@ -14,12 +14,24 @@ package org.eclipse.papyrus.infra.internationalization.common.utils; +import static org.eclipse.papyrus.infra.internationalization.common.utils.InternationalizationPreferencesConstants.LANGUAGE_PREFERENCE; +import static org.eclipse.papyrus.infra.internationalization.common.utils.InternationalizationPreferencesConstants.USE_INTERNATIONALIZATION_PREFERENCE; + +import java.util.Collection; +import java.util.HashSet; import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceProxy; +import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.CommonPlugin; import org.eclipse.emf.common.util.URI; @@ -27,18 +39,44 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.papyrus.infra.core.resource.ModelSet; import org.eclipse.papyrus.infra.core.resource.sasheditor.DiModel; import org.eclipse.papyrus.infra.internationalization.common.Activator; +import org.eclipse.papyrus.infra.internationalization.common.IPreferenceStoreListener; /** * The internationalization preference utils methods which allow to get or * change the internationalization preference value. */ public class InternationalizationPreferencesUtils { - + private static final CopyOnWriteArrayList<InternationalizationPreferenceListener> listeners = new CopyOnWriteArrayList<>(); - + + static { + IPreferenceStoreListener preferenceStoreListener = new IPreferenceStoreListener() { + private final Map<IPreferenceStore, IPropertyChangeListener> forwarders = new WeakHashMap<>(); + + @Override + public void preferenceStoreCreated(IProject project, String papyrusProject, IPreferenceStore store) { + store.addPropertyChangeListener(forwarders.computeIfAbsent(store, __ -> createForwarder(project, papyrusProject))); + } + + @Override + public void preferenceStoreDisposed(IProject project, String papyrusProject, IPreferenceStore store) { + // The equal object will be removed from the store's listeners + store.removePropertyChangeListener(forwarders.get(store)); + } + + IPropertyChangeListener createForwarder(IProject project, String papyrusProject) { + return event -> preferenceStorePropertyChanged(project, papyrusProject, event); + } + }; + + Activator.getDefault().addPreferenceStoreListener(preferenceStoreListener); + } + /** * This allows to get the load of internationalization preference value. * @@ -46,17 +84,17 @@ public class InternationalizationPreferencesUtils { */ public static boolean isInternationalizationNeedToBeLoaded() { boolean result = false; - + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); - if(null != preferenceStore) { - if(preferenceStore.contains(InternationalizationPreferencesConstants.LOAD_INTERNATIONALIZATION)) { + if (null != preferenceStore) { + if (preferenceStore.contains(InternationalizationPreferencesConstants.LOAD_INTERNATIONALIZATION)) { result = preferenceStore.getBoolean(InternationalizationPreferencesConstants.LOAD_INTERNATIONALIZATION); } } - + return result; } - + /** * This allows to get the load of internationalization of external files preference value. * @@ -64,17 +102,17 @@ public class InternationalizationPreferencesUtils { */ public static boolean isInternationalizationExternalFilesNeedToBeLoaded() { boolean result = false; - + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); - if(null != preferenceStore) { - if(preferenceStore.contains(InternationalizationPreferencesConstants.LOAD_INTERNATIONALIZATION_OF_EXTERNAL_FILES)) { + if (null != preferenceStore) { + if (preferenceStore.contains(InternationalizationPreferencesConstants.LOAD_INTERNATIONALIZATION_OF_EXTERNAL_FILES)) { result = preferenceStore.getBoolean(InternationalizationPreferencesConstants.LOAD_INTERNATIONALIZATION_OF_EXTERNAL_FILES); } } - + return result; } - + /** * Get the preference store for the project containing the {@link EObject} @@ -185,12 +223,8 @@ public class InternationalizationPreferencesUtils { final IPreferenceStore preferenceStore = getPreferenceStore(resourceURI); if (null != preferenceStore) { - preferenceStore.setValue(InternationalizationPreferencesConstants.USE_INTERNATIONALIZATION_PREFERENCE, + preferenceStore.setValue(USE_INTERNATIONALIZATION_PREFERENCE, value); - - if (hasListeners()) { - fire(new InternationalizationPreferenceChangeEvent(preferenceStore, resourceURI, value)); - } } } @@ -241,9 +275,9 @@ public class InternationalizationPreferencesUtils { final IPreferenceStore preferenceStore = getPreferenceStore(resourceURI); if (null != preferenceStore && preferenceStore - .contains(InternationalizationPreferencesConstants.USE_INTERNATIONALIZATION_PREFERENCE)) { + .contains(USE_INTERNATIONALIZATION_PREFERENCE)) { result = preferenceStore - .getBoolean(InternationalizationPreferencesConstants.USE_INTERNATIONALIZATION_PREFERENCE); + .getBoolean(USE_INTERNATIONALIZATION_PREFERENCE); } return result; @@ -262,8 +296,8 @@ public class InternationalizationPreferencesUtils { final IPreferenceStore preferenceStore = getPreferenceStore(uri); if (null != preferenceStore - && preferenceStore.contains(InternationalizationPreferencesConstants.LANGUAGE_PREFERENCE)) { - result = preferenceStore.getString(InternationalizationPreferencesConstants.LANGUAGE_PREFERENCE); + && preferenceStore.contains(LANGUAGE_PREFERENCE)) { + result = preferenceStore.getString(LANGUAGE_PREFERENCE); } return result; @@ -351,20 +385,14 @@ public class InternationalizationPreferencesUtils { final IPreferenceStore preferenceStore = getPreferenceStore(resourceURI); if (null != preferenceStore) { - preferenceStore.setValue(InternationalizationPreferencesConstants.LANGUAGE_PREFERENCE, language); - - if (hasListeners()) { - Locale locale = (language == null) ? Locale.getDefault() - : LocaleNameResolver.getLocaleFromString(language); - fire(new InternationalizationPreferenceChangeEvent(preferenceStore, resourceURI, locale)); - } + preferenceStore.setValue(LANGUAGE_PREFERENCE, language); } } - + private static boolean hasListeners() { return !listeners.isEmpty(); } - + private static void fire(InternationalizationPreferenceChangeEvent event) { for (InternationalizationPreferenceListener next : listeners) { try { @@ -374,28 +402,103 @@ public class InternationalizationPreferencesUtils { } } } - + /** * Adds a {@code listener} for changes in the internationalization preferences of resources. * Has no effect if the {@code listener} is already attached. * - * @param listener a listener to add + * @param listener + * a listener to add * * @since 1.1 */ public static void addPreferenceListener(InternationalizationPreferenceListener listener) { listeners.addIfAbsent(listener); } - + /** * Removes a {@code listener} for changes in the internationalization preferences of resources. * Has no effect if the {@code listener} is not currently attached. * - * @param listener a listener to remove + * @param listener + * a listener to remove * * @since 1.1 */ public static void removePreferenceListener(InternationalizationPreferenceListener listener) { listeners.remove(listener); } + + static void preferenceStorePropertyChanged(IProject project, String papyrusProjectName, PropertyChangeEvent event) { + if (!hasListeners()) { + return; // Nobody to notify + } + + // FIXME: The preferences implementation assumes unique model resource names in the project + Collection<URI> uris = getURIs(project, papyrusProjectName); + switch (event.getProperty()) { + case USE_INTERNATIONALIZATION_PREFERENCE: + boolean newUse; + if (event.getNewValue() instanceof Boolean) { + newUse = ((Boolean) event.getNewValue()).booleanValue(); + } else { + newUse = Boolean.valueOf(String.valueOf(event.getNewValue())); + } + + uris.forEach(uri -> fire(new InternationalizationPreferenceChangeEvent(event.getSource(), + uri, newUse))); + break; + case LANGUAGE_PREFERENCE: + Locale locale = (event.getNewValue() == null) ? Locale.getDefault() + : LocaleNameResolver.getLocaleFromString(String.valueOf(event.getNewValue())); + uris.forEach(uri -> fire(new InternationalizationPreferenceChangeEvent(event.getSource(), uri, locale))); + break; + default: + // Nobody interested + break; + } + } + + private static Set<URI> getURIs(IProject project, String papyrusProjectName) { + Set<URI> result = new HashSet<>(); + + try { + project.accept(new IResourceProxyVisitor() { + + @Override + public boolean visit(IResourceProxy proxy) throws CoreException { + if (proxy.getType() == IResource.FILE) { + String name = trimFileExtension(proxy.getName()); + if (papyrusProjectName.equals(name)) { + // Normalize the result to contain only the DI resource URIs + // if DI resources exist + URI uri = URI.createPlatformResourceURI(proxy.requestFullPath().toString(), true); + URI trim = uri.trimFileExtension(); + if (DiModel.DI_FILE_EXTENSION.equals(uri.fileExtension())) { + result.removeIf(u -> u.trimFileExtension().equals(trim)); + result.add(uri); + } else { + URI diURI = trim.appendFileExtension(DiModel.DI_FILE_EXTENSION); + if (!result.contains(diURI)) { + result.add(uri); + } + } + } + } + return true; + } + + private String trimFileExtension(String name) { + int dot = name.lastIndexOf('.'); + // Only accept resources that have a file extension, as all Papyrus model + // resources must + return (dot >= 0) ? name.substring(0, dot) : null; + } + }, 0); + } catch (CoreException e) { + Activator.log.log(e.getStatus()); + } + + return result; + } } |