/*
* Freeplane - mind map editor
* Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
* This file is created by Dimitry Polivaev in 2008.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.freeplane.core.resources;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Vector;
import org.freeplane.core.ui.AFreeplaneAction;
import org.freeplane.core.util.FileUtils;
import org.freeplane.core.util.LogUtils;
import org.freeplane.features.mode.AController.IActionOnChange;
import org.freeplane.features.mode.Controller;
/**
* @author Dimitry Polivaev
*/
public abstract class ResourceController {
public static final String FREEPLANE_PROPERTIES = "/freeplane.properties";
public static final String LOCAL_PROPERTIES = "LocalProperties.";
public static final String RESOURCE_DRAW_RECTANGLE_FOR_SELECTION = "standarddrawrectangleforselection";
// some plugins have their own file for registration of defaults
public static final String PLUGIN_DEFAULTS_RESOURCE = "defaults.properties";
static public ResourceController getResourceController() {
return Controller.getCurrentController().getResourceController();
}
final private List<IFreeplanePropertyListener> propertyChangeListeners = new Vector<IFreeplanePropertyListener>();
private ResourceBundles resources;
public static final String FREEPLANE_RESOURCE_URL_PROTOCOL = "freeplaneresource";
public static final String FREEPLANE_WORKSPACE_URL_PROTOCOL = "workspace";
public static final String OBJECT_TYPE = "ObjectType";
public ResourceController() {
super();
}
public void addLanguageResources(final String language, final URL url) {
resources.addResources(language, url);
}
public void addLanguageResources(final String language, final Map<String, String> resources) {
this.resources.addResources(language, resources);
}
public void addPropertyChangeListener(final IFreeplanePropertyListener listener) {
propertyChangeListeners.add(listener);
}
/**
* @param listener
* The new listener. All currently available properties are sent
* to the listener after registration. Here, the oldValue
* parameter is set to null.
*/
public void addPropertyChangeListenerAndPropagate(final IFreeplanePropertyListener listener) {
addPropertyChangeListener(listener);
for (final Entry<Object, Object> entry : getProperties().entrySet()) {
final String key = (String) entry.getKey();
listener.propertyChanged(key, (String) entry.getValue(), null);
}
}
protected void loadAnotherLanguage() {
resources.loadAnotherLanguage();
}
protected void firePropertyChanged(final String property, final String value, final String oldValue) {
if (oldValue == null || !oldValue.equals(value)) {
setProperty(property, value);
for (final IFreeplanePropertyListener listener : getPropertyChangeListeners()) {
listener.propertyChanged(property, value, oldValue);
}
}
}
public boolean getBooleanProperty(final String key) {
return Boolean.parseBoolean(getProperty(key));
}
@SuppressWarnings("unchecked")
public <T extends Enum<T>> T getEnumProperty(String propertyName, Enum<T> defaultValue) {
try{
final String cacheProptertyValue = getProperty(propertyName).toUpperCase();
defaultValue = Enum.valueOf(defaultValue.getClass(), cacheProptertyValue);
}
catch (Exception e) {
LogUtils.severe(e);
}
return (T)defaultValue;
}
/**
* @param resourcesNodeTextColor
* @return
*/
public String getDefaultProperty(final String key) {
return null;
}
/** register defaults in freeplane.properties respectively defaults.properties instead! */
public double getDoubleProperty(final String key, final double defaultValue) {
try {
return Double.parseDouble(ResourceController.getResourceController().getProperty(key));
}
catch (final Exception e) {
return defaultValue;
}
}
/**
* @return
*/
abstract public String getFreeplaneUserDirectory();
/** register defaults in freeplane.properties respectively defaults.properties instead! */
public int getIntProperty(final String key, final int defaultValue) {
try {
return Integer.parseInt(getProperty(key));
}
catch (final NumberFormatException nfe) {
return defaultValue;
}
}
public int getIntProperty(String key) {
return Integer.parseInt(getProperty(key));
}
public double getDoubleProperty(String key) {
return Double.parseDouble(getProperty(key));
}
/** register defaults in freeplane.properties respectively defaults.properties instead. */
public long getLongProperty(final String key, final int defaultValue) {
try {
return Long.parseLong(getProperty(key));
}
catch (final NumberFormatException nfe) {
return defaultValue;
}
}
abstract public Properties getProperties();
abstract public String getProperty(final String key);
/** register defaults in freeplane.properties respectively defaults.properties instead! */
public String getProperty(final String key, final String value) {
return getProperties().getProperty(key, value);
}
public Collection<IFreeplanePropertyListener> getPropertyChangeListeners() {
return Collections.unmodifiableCollection(propertyChangeListeners);
}
public URL getResource(final String name) {
return getClass().getResource(name);
}
public String getResourceBaseDir() {
return "";
}
public String getInstallationBaseDir() {
return "";
}
/** Returns the ResourceBundle with the current language */
public ResourceBundle getResources() {
if (resources == null) {
resources = new ResourceBundles(this);
}
return resources;
}
public String getLanguageCode() {
return resources.getLanguageCode();
}
public String getDefaultLanguageCode() {
return resources.getDefaultLanguageCode();
}
public String getText(final String key, final String resource) {
return ((ResourceBundles) getResources()).getResourceString(key, resource);
}
protected void init() {
}
public void removePropertyChangeListener(final IFreeplanePropertyListener listener) {
propertyChangeListeners.remove(listener);
}
abstract public void saveProperties();
abstract public void setDefaultProperty(final String key, final String value);
public void setProperty(final String property, final boolean value) {
setProperty(property, Boolean.toString(value));
}
abstract public void setProperty(final String property, final String value);
/** adds properties from url to properties. Existing properties in resultProps will be overridden.
* @return false if anything went wrong. */
protected static boolean loadProperties(Properties resultProps, final URL url) {
InputStream in = null;
try {
in = new BufferedInputStream(url.openStream());
resultProps.load(in);
LogUtils.info("Loaded properties from " + url);
return true;
}
catch (final Exception ex) {
System.err.println("Could not load properties from " + url);
}
finally {
FileUtils.silentlyClose(in);
}
return false;
}
/** will add properties from propertiesUrl if they don't exist yet. */
public void addDefaults(URL propertiesUrl) {
Properties props = new Properties();
loadProperties(props, propertiesUrl);
addDefaults(props);
}
/** use generic to make it useable with Properties. KT and VT must be of type String. */
public <KT, VT> void addDefaults(Map<KT, VT> defaultProperties) {
for (Entry<KT, VT> entry : defaultProperties.entrySet()) {
if (getProperty((String) entry.getKey()) == null)
setProperty((String) entry.getKey(), (String) entry.getValue());
}
}
public boolean isApplet() {
return false;
}
public void removePropertyChangeListener(final Class<? extends IActionOnChange> clazz, final AFreeplaneAction action) {
final Iterator<IFreeplanePropertyListener> iterator = propertyChangeListeners.iterator();
while (iterator.hasNext()) {
final IFreeplanePropertyListener next = iterator.next();
if (next instanceof IActionOnChange && ((IActionOnChange) next).getAction() == action) {
iterator.remove();
return;
}
}
}
}