/*
* Presets.java
* (FScape)
*
* Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de
*/
package de.sciss.fscape.prop;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
/**
* Abgeleitete Properties-Klasse zur Verwaltung von Presets
* Einem Key-Namen stet als Value eine Properties-Liste gegenueber, die automatisch
* in einen "String" umgewandelt wird (durch Ersetzen der Linefeeds)
*/
public class Presets
extends BasicProperties {
// -------- public variables --------
/**
* Name fuer den Default-Preset
*/
public static final String DEFAULT = "(default)";
private static final Comparator<String> caseInsensitiveComp = new Comparator<String>() {
public int compare( String a, String b ) {
return a.toUpperCase().compareTo(b.toUpperCase() );
}
};
// -------- public methods --------
/**
* Legt das Presets-Objekt an mit entsprechenden Default-Eintraegen
*
* @param owner Inhaber der Preferences (daraus wird der Name abgeleitet)
* @param defPreset voreingestellter Preset
*/
public Presets( Class owner, Properties defPreset )
{
// default Properties, der Rest wird von oben gemanagt
super( owner, createDefaults( defPreset ), "pst" );
}
/**
* Aendert einen Preset bzw. legt diesen ggf. an
*
* @param name Preset-Name
* @param val Werte des Presets in Properties-Form
* @return Wert als String, null bei Fehler
*/
public String setPreset( String name, Properties val )
{
name = stringToKey( name );
String strVal = Presets.propertiesToValue( val );
if( strVal != null ) {
synchronized( this ) {
put( name, strVal );
modified = true; // indicate that presets should be saved on exit
}
}
return strVal;
}
/**
* Besorgt einen Preset
*
* @param name Preset-Name
* @return entsprechende Werte als Properties-Object oder null bei Fehler
*/
public Properties getPreset( String name )
{
name = stringToKey( name );
String strVal;
synchronized( this ) {
strVal = getProperty( name );
}
Properties val = null;
if( strVal != null ) {
val = Presets.valueToProperties( strVal );
}
return val;
}
public boolean containsPreset( String name )
{
synchronized( this ) {
return this.containsKey( stringToKey( name ));
}
}
/**
* Loescht einen Preset
*
* @param name Preset-Name
* @return vorheriger Wert als String oder null wenn nicht existent
*/
public String removePreset( String name )
{
String val;
name = stringToKey( name );
synchronized( this ) {
val = (String) remove( name );
if( val != null) modified = true;
}
return val;
}
/**
* Return List of all Preset-Names (sorted)
*/
public List presetNames()
{
synchronized( this ) {
final List<String> li = new ArrayList<String>( this.size() );
final Enumeration e = propertyNames();
while( e.hasMoreElements() ) {
li.add( keyToString( (String) e.nextElement() ));
}
Collections.sort( li, caseInsensitiveComp );
return li;
}
}
/**
* Schreibt die uebergebenen Properties in einen ByteStream und
* liefert diesen als String zurueck
*
* @return null bei Fehler
*/
public static String propertiesToValue( Properties val )
{
final OutputStream outStream = new ByteArrayOutputStream();
try {
val.store( outStream, null );
final String strVal = outStream.toString(); // now we have the Properties as a String
outStream.close();
return strVal;
}
catch( IOException e ) {
return null;
}
}
/**
* Schreibt die uebergebenen String in einen ByteStream und
* liefert diesen als Properties-Objekt zurueck
*
* @param strVal null erlaubt, ergibt aber auch null als Ergebnis!
* @return null bei Fehler
*/
public static Properties valueToProperties(String strVal) {
final Properties val = new Properties();
try {
if (strVal != null) {
final InputStream inStream = new ByteArrayInputStream(strVal.getBytes());
val.load(inStream); // now we have the String as a Properites-Object
inStream.close();
return val;
}
} catch (IOException e) { /* nothing */ }
return null;
}
// -------- protected methods --------
/*
* Filtert die unerlaubten Zeichen eines Presetnamens
*
* @return gefilterter Name, einige Zeichen werden ersetzt durch Unicode-Symbole
*/
protected static String stringToKey( String str )
{
String unicode;
for( int i = 0; i < str.length(); i++ ) {
final char c = str.charAt( i );
if( ("#!=:".indexOf( c ) >= 0) ||
Character.isWhitespace( c ) ) { // verbotenes Zeichen
unicode = Integer.toString( (int) c );
unicode = "\\u0000".substring( 0, 6 - unicode.length() ) + unicode; // Ersatzstring
str = str.substring( 0, i ) + unicode + str.substring( i + 1 ); // ...einfuegen
}
}
return str;
}
/*
* Konvertiert einen Presetnamen in einen String,
* evtl. gefiltertete Zeichen werden wieder zurueckkonvertiert
*/
protected static String keyToString( String key )
{
try {
int i;
while( (i = key.indexOf( "\\u" )) >= 0 ) {
final char c = (char) Integer.parseInt( key.substring( i + 2, i + 6 ));
key = key.substring( 0, i ) + c + key.substring( i + 6 );
}
}
catch( IndexOutOfBoundsException ignored) {} // nothing we can do unfortunately
catch( NumberFormatException ignored) {}
return key;
}
protected static Properties createDefaults( Properties defaultVal )
{
final Properties defaults = new Properties();
final String strVal = propertiesToValue( defaultVal );
if( strVal != null ) {
defaults.put( DEFAULT, strVal );
}
return defaults;
}
}