Bug 22533 - [runtime] Preferences.contains() returns false even if property has been set
Summary: [runtime] Preferences.contains() returns false even if property has been set
Status: RESOLVED WONTFIX
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Resources (show other bugs)
Version: 2.0   Edit
Hardware: PC Windows 2000
: P2 critical (vote)
Target Milestone: 2.1   Edit
Assignee: Platform-Resources-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 18938 (view as bug list)
Depends on:
Blocks:
 
Reported: 2002-08-19 11:56 EDT by Dani Megert CLA
Modified: 2004-04-16 14:12 EDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dani Megert CLA 2002-08-19 11:56:45 EDT
Build: 20020819

0. get store (instance of org.eclipse.core.runtime.Preferences)
1. use store.setValue('key', false);
2. use store.contains('key');
==> returns false which is a severe bug in my opinion.

Reason for the bug is that the key is removed from the store if the value is the
same as the default value [ok]. There is a list with default values which is
also checked when using contains [ok] but unfortunately the getDefaultBoolean
method returns false even if there is no default [bug]. It should either return
null or add the key to the default list as soon as returning 'false'
Comment 1 Dani Megert CLA 2002-08-19 11:58:50 EDT
*** Bug 18938 has been marked as a duplicate of this bug. ***
Comment 2 Dani Megert CLA 2002-08-19 12:10:45 EDT
increasing severity since
- wrong contains() check can cause other clients to fail
- adding a workaround would mean to add a dummy property which I set to
something different than the default value.
Comment 3 John Arthorne CLA 2002-08-20 14:27:28 EDT
I agree this should be changed.  I think in setValue we should add the value to 
the default values table if none is present, even if it is equal to the default 
default value.  This behaviour happens for all setValue methods where the value 
being set is equal to the default default value.
Comment 4 Dani Megert CLA 2002-10-11 04:38:50 EDT
Any idea when this bug gets addressed - 2.1? It causes filter settings being
lost (see bug  18938).
Comment 5 DJ Houghton CLA 2002-10-30 12:46:28 EST
The reason that the value isn't set in the table of defaults is because it is 
equal to the "default default".

So the following code pattern does return the correct results:
0. get store (instance of org.eclipse.core.runtime.Preferences)
1. use store.setValue('key', false);
2. use store.getBooleanValue('key');
==> returns false

If you want to have an explicit value for the default, use can use setDefault
(String, boolean). If you use this, then the #contains call returns "true".

Adding Jeem to CC for comment.
Comment 6 Jim des Rivieres CLA 2002-10-30 14:30:58 EST
Preferences are a table structure with 2 levels of setting: a default setting 
and a real setting. This characteristic (which was carried over from the JFace
preference store) is thoroughly described in the javadoc, and everything is 
working as spec'd. 

Going back to the matter of losing filter settings being lost (bug 18938), I 
think it see the problem. You have a user setting that is not a user 
preference, correct?. If the user does something, you want to persistently 
remember whatever true/false setting the user specifies. If the user does 
nothing, you don't want to persistently remember anything.

If you just use store.setValue(key,b), nothing gets saved when
the store is written out for keys where b=false (because false is the
default value, and the store doesn't save default values). If you instead use 
store.setDefaultValue(key,b), nothing ever gets saved when the store is 
written out (because default values are never saved).

Conclusion: You can't use a preference store to persistently save a boolean 
user setting.

Notice that if we were talking about a true user *preference* setting,
the specified behavior is generally what you want: save only a 'delta' that 
captures how this user's preference settings differs from the defaults, without
capturing the defaults.

With only a slight bit of complication, you can get things to work out by 
storing a string encoding of a boolean:

store.setValue(key, (b ? "T" : "F"));
store.contains(key) always returns true
and store.getString(key).equals("T") == b provided store.contains(key)

If this does indeed solve your original problem, I suggest that we improve
the Javadoc for 2.1 (and the preference article?) to document this gotcha and
explain the workaround.








Comment 7 Dani Megert CLA 2002-10-31 02:11:57 EST
Of course I could code the workaround and you could modifiy the Javadoc (though
being an API change in my opinion and hence not a good fix for 2.1) but I still
can't find any good argument (except implementation details), why
"store.contains(key)" should return false after using "store.set(key, value)".
Comment 8 Jim des Rivieres CLA 2002-10-31 08:46:10 EST
"store.contains(key)" return false after using "store.set(key, value)" 
when "store.getDefaultBoolean(key) == false" because the user has not set the 
preference to anything different than the default and there is therefore no 
need or desire to store an explicit different-from-default value.
Comment 9 Dani Megert CLA 2002-10-31 09:04:27 EST
>there is therefore no 
>need or desire to store an explicit different-from-default value.
This is OK for me (i.e. how the store is internally implemented) but it is not
OK that the store loses the information whether it contains data (be it default
or not) for a given key.
Comment 10 Jim des Rivieres CLA 2002-10-31 09:28:16 EST
This is not an implementation issue --- it is how the preference mechanism is 
designed to work (i.e., to never store values that are different from the 
default).

Example preference behavior:
1. User is shown preference "x" in unchecked state (the default setting, false)
store.getBoolean("x");
2. User checks the check box
store.setValue("x",true);
3. User changes her mind and unchecks the check box
store.setValue("x",false);
4. User hits OK

The desired behavior is that the store does not contain("x"). When the store
is saved, no setting for "x" is written out. In a subsequent session, the 
user will get the default setting for "x". If the defaullt setting is still
"false", they get exactly that. But if the default setting is now "true" 
(there are several way preference default settings can be changed, including 
from the comand line), then they get "true".
Comment 11 Dani Megert CLA 2002-10-31 10:26:21 EST
I don't understand the discussion: The API for contains explicitly says that it
considers default values:
	/**
	 * Returns whether the given property is known to this preference object,
	 * either by having an explicit setting or by having a default
	 * setting.

You might change the API/Javadoc for 3.0 but for the current stream it is a bug.
Comment 12 John Arthorne CLA 2002-11-21 17:52:21 EST
It also says in the class javadoc that explicitly setting to the default value
will delete the preference:

 * ... The existing settings can be changed and new properties
 * can be set (<code>setValue</code>). If the values specified is the same as 
 * the default value, the explicit setting is deleted from the top layer.
Comment 13 Dani Megert CLA 2002-11-22 02:52:26 EST
Is I know but isContains also says:
 * either by having an explicit setting or by having a default setting.
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Comment 14 DJ Houghton CLA 2003-02-18 10:22:51 EST
The Preferences code (originally copied from JFace preferences) goes to great 
lengths to not store default values. This behaviour won't be changed.

Closing as WONTFIX.
Comment 15 DJ Houghton CLA 2004-04-16 14:12:36 EDT
Fixed in the 3.0 stream.
See bug 51309.