/*******************************************************************************
* Copyright (c) 2012 VMware, Inc.
* 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:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
/*
* @author Kaitlin Duck Sherwood
*/
package org.springframework.ide.eclipse.wizard.template.util;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.springframework.ide.eclipse.wizard.WizardPlugin;
import org.springsource.ide.eclipse.commons.content.core.ContentPlugin;
public abstract class AbstractNameUrlPreferenceModel {
private final IEclipsePreferences store;
private final IEclipsePreferences defaultStore;
private String currentString;
protected boolean optionalFlagValue;
private final List<PropertyChangeListener> listeners;
protected abstract IEclipsePreferences getStore();
protected abstract String getStoreKey();
protected abstract String getDefaultFilename();
protected abstract IEclipsePreferences getDefaultStore();
public AbstractNameUrlPreferenceModel() {
listeners = new CopyOnWriteArrayList<PropertyChangeListener>();
store = getStore();
defaultStore = getDefaultStore();
if (store == null) {
String title = NLS.bind("Serious error", null);
String message = NLS
.bind("This is a serious error: we didn't think this could happen. Please tell the STS team that there was no preferences store for the Help bundle."
+ "The issue tracker is at https://issuetracker.springsource.com/browse/STS", null);
MessageDialog.openError(null, title, message);
}
// You always want the defaults set;
// you might not want to overwrite the store
setDefaults();
// side effect: if the instance store is empty, set the instance store
// to the default values
revert();
// If don't persist it here, it isn't available to the ResourceProvider
persist();
}
public void revert() {
currentString = store.get(getStoreKey(), null);
if (currentString == null) {
currentString = defaultStore.get(getStoreKey(), "");
}
// don't need to be as careful with the optional flag because
// its default is something reasonable; also it can't be set to
// null to show that it has not been set
}
// This initializes the defaults; it is NOT ever called by the user
// or even reached by something the user does.
protected void setDefaults() {
InputStream defaultsStream;
try {
defaultsStream = FileLocator.openStream(WizardPlugin.getDefault().getBundle(), new Path(
getDefaultFilename()), false);
Properties urlProperties = new Properties();
urlProperties.load(defaultsStream);
String encodedString = "";
for (Object key : urlProperties.keySet()) {
if (key instanceof String && urlProperties.get(key) instanceof String) {
try {
encodedString = encodedString
+ (new NameUrlPair((String) key, urlProperties.getProperty((String) key)))
.asCombinedString();
}
catch (URISyntaxException e) {
String title = NLS.bind("Malformed URL", null);
String message = NLS.bind("The {0} is not a legal URL; ignoring.", urlProperties.get(key));
MessageDialog.openError(null, title, message);
}
}
}
defaultStore.put(getStoreKey(), encodedString);
}
catch (IOException e1) {
String title = NLS.bind("Could not read defaults", null);
String message = NLS.bind(
"Could not read defaults from file {0}; check that the file exists and is readable",
getDefaultFilename());
MessageDialog.openError(null, title, message);
}
}
public ArrayList<NameUrlPair> getElements() {
if (currentString == null) {
currentString = defaultStore.get(getStoreKey(), "");
}
return NameUrlPair.decodeMultipleNameUrlStrings(currentString);
}
public String replaceNameUrlPairInEncodedString(NameUrlPair oldNameUrl, NameUrlPair newNameUrl) {
currentString = currentString.replaceFirst(oldNameUrl.asCombinedString(), newNameUrl.asCombinedString());
return currentString;
}
public String removeNameUrlPairInEncodedString(NameUrlPair oldNameUrl) {
String combinedString = oldNameUrl.asCombinedString();
String adjustedString = Pattern.quote(combinedString);
currentString = currentString.replaceFirst(adjustedString, "");
return currentString;
}
public String addNameUrlPairInEncodedString(NameUrlPair newNameUrl) {
currentString = currentString + newNameUrl.asCombinedString();
return currentString;
}
public boolean persist() {
boolean didChangeFlag = false;
normalizeCurrentStringOrder();
if (!currentString.equals(store.get(getStoreKey(), null))) {
Assert.isNotNull(currentString, "INTERNAL ERROR: current string should not be null in " + this.getClass());
store.put(getStoreKey(), currentString);
didChangeFlag = true;
}
boolean oldValue = getStore().getBoolean(getStoreOptionalFlagKey(), optionalFlagDefault());
boolean newValue = getOptionalFlagValue();
if (oldValue != newValue) {
didChangeFlag = true;
getStore().putBoolean(getStoreOptionalFlagKey(), getOptionalFlagValue());
}
if (didChangeFlag) {
ContentPlugin.getDefault().getManager().setDirty();
}
return didChangeFlag;
}
private void normalizeCurrentStringOrder() {
List<NameUrlPair> sortedItems = NameUrlPair.decodeMultipleNameUrlStrings(currentString);
Collections.sort(sortedItems, new Comparator<NameUrlPair>() {
public int compare(NameUrlPair o1, NameUrlPair o2) {
return o1.getUrlString().compareTo(o2.getUrlString());
}
});
currentString = "";
for (NameUrlPair nameUrlPair : sortedItems) {
currentString += nameUrlPair.asCombinedString();
}
}
protected void clearNonDefaults() {
currentString = defaultStore.get(getStoreKey(), null);
}
protected abstract String getStoreOptionalFlagKey();
protected boolean optionalFlagDefault() {
return false;
}
// The templates need somewhere to keep a boolean of whether or
// not to show self-hosted templates in the New Template Wizard.
protected void setOptionalFlagValue(boolean flagValue) {
optionalFlagValue = flagValue;
}
protected boolean getOptionalFlagValue() {
return optionalFlagValue;
}
public void addListener(PropertyChangeListener listener) {
listeners.add(listener);
}
public void removeListener(PropertyChangeListener listener) {
listeners.remove(listener);
}
}