Bug 21756 - [PropertiesView] incorrect SetPropertyValueCommand#undo implementation
Summary: [PropertiesView] incorrect SetPropertyValueCommand#undo implementation
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows 2000
: P2 normal (vote)
Target Milestone: 3.1 M7   Edit
Assignee: Nick Edgar CLA
QA Contact:
URL:
Whiteboard:
Keywords: api, helpwanted
Depends on:
Blocks: 54250
  Show dependency tree
 
Reported: 2002-07-22 09:44 EDT by Gunnar Wagenknecht CLA
Modified: 2005-05-10 15:26 EDT (History)
7 users (show)

See Also:


Attachments
Patch for IPropertySource JavaDoc (3.69 KB, patch)
2004-03-10 04:54 EST, Gunnar Wagenknecht CLA
no flags Details | Diff
Patch to add new API (instead of JavaDoc patch) (5.88 KB, patch)
2004-03-10 05:03 EST, Gunnar Wagenknecht CLA
no flags Details | Diff
Proposed patch with fixed JavaDoc and new interface (16.33 KB, patch)
2004-05-03 13:24 EDT, Gunnar Wagenknecht CLA
no flags Details | Diff
New patch with corrected JavaDoc and interfaces (16.28 KB, patch)
2005-05-02 12:23 EDT, Gunnar Wagenknecht CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Gunnar Wagenknecht CLA 2002-07-22 09:44:46 EDT
Randy,

"Randy Hudson" <none@ibm.com> schrieb im Newsbeitrag 
news:ahgvkq$e2p$1@rogue.oti.com...
> Step through CommandStack.undo().
> The command created by the undoable PS entry will call some API on
> IPropertySource to set/reset the value.  This should cause your model to
> fire a change.

I found that there is a SetPropertyValueCommand and this command does the undo 
but not correctly IMHO.

If IPropertySource.isPropertySet returns true, the SetPropertyValueCommand 
stores the old value and restores it on undo. But if 
IPropertySource.isPropertySet returns false, the SetPropertyValueCommand simply 
resets the property value instead of restoring the old one.

A proper implementation of IPropertySource.isPropertySet "returns false if the 
notion of a default value is not meaningful for the specified property". This 
is the case in my model. With the currently implementation of 
SetPropertyValueCommand it is not possible to undo a property value change if 
your model doesn't use default values.

Will you change the implementation?

Cu, Gunnar
Comment 1 Randy Hudson CLA 2002-07-22 11:34:29 EDT
The JavaDOC for IPropertySource is incorrect.  I argued a while back (before 
1.0) that this method should be called isPropertyResettable(Object ID).  You 
*have* to use the method to mean that.  The JavaDOC states:

"false if the notion of a default value is not meaningful".  *BUT* false is 
ALSO returned in the case where a default value *IS* meaningful and the 
property's value is currently the default value.  You can't overload the 
meaning of false in this way.  If you do, the method is meaningless.  How can 
GEF know whether to call setPropertyValue(ID, oldValue), or resetPropertyValue
(ID)?

You must implement resetPropertyValue(Object ID) for all properties which 
return isPropertySet(ID) FALSE, because FALSE means that the current value is 
the DEFAULT value, not that default is undefined.
Comment 2 Richard Kulp CLA 2002-09-03 13:25:16 EDT
What we really need is a method on IPropertySource that says canPropertyBeReset
(Object propertykey). In addition to isPropertySet. isPropertySet is absolutely 
necessary for those properties that can be reset. As Randy noted, this method 
was impropertly overloaded within these meanings.

But can we have the API changed now to include this new method. It would be a 
valuable addition because then IPropertySheetEntry could use this method and 
then the PropertySheet itself could disable the reset property value action if 
the property sheet entry returned false for this. (Note: PropertySheet would 
have to go through the PropertySheetEntry for this, it should not go directly 
to the IPropertySource because it doesn't know anything about the 
IPropertySource).

Comment 3 Randy Hudson CLA 2002-09-04 12:07:02 EDT
I agree with what Rich said.  But I think the new API should be called 
isPropertyResetable().

Here are the 3 cases:
1) foo.x = [default value];
2) foo.x = 5, but a default value exists.
3) foo.x = 5, but there is no such thing as a default.

As a result:
  case:  undoShouldReset:   resetButtonEnabled:
-----------------------------------------------
   (1)        TRUE                 FALSE
   (2)        FALSE                TRUE
   (3)        FALSE                FALSE

If you decide that disabling the reset button is not important, then cases 2&3 
can be merged.  But in order to merge 2&3, the JavaDOC should state that 
isPropertySet(Object) must return *true* if the notion of a default property 
does not exist.  It currently reads the opposite.

If reset button does not disable, the user will click and nothing will happen.  
Also, a no-op will be on the Undo/Redo stack.
Comment 4 Randy Hudson CLA 2004-01-28 13:47:31 EST
Please consider for 3.0.  In the very least, update the javadoc.
Comment 5 Gunnar Wagenknecht CLA 2004-03-10 03:16:38 EST
It is very bad because this breaks nearly every GEF application. Undo doesn't 
work for any of our property sources in GEF.

The time for breaking API changes is now over so we have to define a new 
interface IPropertySourceExtension.

The API of IPropertySource is simply not clear in this situation. Will it be 
possible to include this in 3.0 if prepare a patch for this issue?

If yes, what is allowed and what is not allowed?
Comment 6 Gunnar Wagenknecht CLA 2004-03-10 04:54:39 EST
Created attachment 8452 [details]
Patch for IPropertySource JavaDoc

This is a patch for IPropertySource.java (Revision 1.6) that only corrects the
JavaDoc.
Comment 7 Gunnar Wagenknecht CLA 2004-03-10 05:03:06 EST
Created attachment 8453 [details]
Patch to add new API (instead of JavaDoc patch)

This patch should be used INSTEAD the IPropertySource-JavaDoc patch to add an
additional interface (IPropertySourceExtension) that provides the API for
asking a property source if a property is resettable.

This patch also includes modification of PropertySheetEntry to use the new API.
It must be applied to package "org.eclipse.ui.views.properties".

The new API must be used additionally to the already existing API:

// reset a value
IPropertySource source = ...
if (source.isPropertySet(descriptor.getId())) {

  boolean doReset = true;

  // call new API to check if property is resettable
  if(source instanceof IPropertySourceExtension) {

    IPropertySourceExtension extendedSource = (IPropertySourceExtension)
source;

    // if property is not resettable then don't do a reset
    if (!extendedSource.isPropertyResettable(descriptor.getId()))
      doReset = false;

  }

  if(doReset)
    source.resetPropertyValue(descriptor.getId());

}
Comment 8 Douglas Pollock CLA 2004-03-10 10:27:32 EST
Nick is the owner of the properties view component area.  This bug doesn't 
cause loss of data, so its either blocker (preventing development work) or 
major (loss of important functionality).  I'm moving it to major.  Feel free to 
change. 
Comment 9 Randy Hudson CLA 2004-03-10 10:53:25 EST
This bug could cause anything to occur.  GEF is interpreting isPropertySet() to 
mean what is should.  If clients expect it to mean what the JavaDoc says, then 
they may have GEF calling resetProperty() when they don't expect it.  What are 
the results of doing this?  Who knows, maybe the client code calls:
System.exit(1) :-)
Comment 10 Gunnar Wagenknecht CLA 2004-03-10 11:03:09 EST
Perfect, than this is critical as one of our clients already had a data loss.

use case: edit property, perform save, perform undo -> property still has the 
new value

If the client doesn't have any backup of the underlying resources (either in 
some versioning system of real backup) then the data is lost.

Note, now we simply return true and averything works fine.
Comment 11 Nick Edgar CLA 2004-03-10 14:49:44 EST
I'll have a look for M9.
Comment 12 Nick Edgar CLA 2004-04-29 14:45:57 EDT
I can't accept the patch above because it changes the spec of
IPropertySource.isPropertySet.  Any existing implementations that conformed to
the old spec will now be "broken".

Randy and Gunnar, can you please collaborate on a revised patch that will
address the needs of GEF without breaking any existing API (even if the old API
was effectively broken).  Nobody on the UI team is actively working in this
area, so if this is going to be fixed for 3.0, it's going to have to come from you.

Comment 13 Randy Hudson CLA 2004-04-29 16:37:31 EDT
GEF will make the proposed fix of checking the value before and after calling 
setValue.  So in a sense, a boolean property can indicate three states!?!

The javadoc could be changed to reflect this without breaking its meaning.  In 
other words, isPropertySet means one of two things if it returns false, and you 
won't know which until you call setProperty. Is the cat dead? You'll have to 
open the box to find out.
Comment 14 Randy Hudson CLA 2004-04-29 16:39:50 EDT
Pratik, track whether isPropertySet(...) changes when we call setProperty.  If 
it does change, then it can be reset.  Otherwise, we need to set it back to the 
old value on undo.
Comment 15 Gunnar Wagenknecht CLA 2004-04-30 03:44:58 EDT
See bug 54250 for a possible patch with lots of comments that may be removed ;)
Comment 16 Randy Hudson CLA 2004-04-30 11:44:45 EDT
Gunnar, I forgot about that bugzilla.  That means these are either dupes, or we 
should route this back to platform UI (and GEF will address the other).  I'll 
let you decide.
Comment 17 Gunnar Wagenknecht CLA 2004-04-30 12:01:37 EDT
Nick, can you explain more detailed? For me the JavaDoc looks just wrong. The 
first patch only the fixes the JavaDoc. The 2nd patch creates new (additional 
API) like it is seen everywhere in the workbench.
Comment 18 Nick Edgar CLA 2004-04-30 13:03:06 EDT
The 2nd patch also includes incompatible changes to old API.
Comment 19 Nick Edgar CLA 2004-04-30 14:20:56 EDT
I also want to ensure you, Randy and any other stakeholders in this PR are in
agreement before reviewing any patch.  Please make it exceedingly easy for me to
put a fix in <g>, since I really need to focus on other areas at the moment.
Comment 20 Randy Hudson CLA 2004-04-30 15:10:54 EDT
I'd have to agree with Gunnars patch.  The current API is misleading. I don't 
see the negative side effects to re-aligning the API with its indended 
meaning.  For those who ignore the change, they would be returning false 
incorrectly.  But, this is not a problem in the propertysheet by itself.  It is 
only a problem for clients which try to implement Undo such as GEF.  But this 
is already broken, so you can't break something futher.
Comment 21 Nick Edgar CLA 2004-05-02 22:12:25 EDT
Sorry, but I'm not going to change the existing API, and go through the hassle
of documenting this breaking change in the porting guide.  If it was incorrect
or ambiguous before, then the new API can correct for it.  Please provide an
updated patch.

Comment 22 Gunnar Wagenknecht CLA 2004-05-03 00:07:58 EDT
Ok, I will update the patch. Randy, do we really need the second interface or 
is it suitiable when we just change the JavaDoc?
Comment 23 Randy Hudson CLA 2004-05-03 10:23:07 EDT
The update to the JavaDoc works in the case where the caller is implementing 
UNDO, and the caller is the one invoking setProperty(), and can therefore query 
the value after setting the property.
Comment 24 Gunnar Wagenknecht CLA 2004-05-03 13:24:46 EDT
Created attachment 10225 [details]
Proposed patch with fixed JavaDoc and new interface

This is a proposed patch that will correct the JavaDoc and add a new interface
IPropertySource2. This interface contains API that will be called to check if a
property is resettable (in PropertySheetEntry#resetPropertyValue).

Corrected API: IPropertySource#isPropertySet(Object)
New API: IPropertySource2#isPropertyResettable(Object)

I also formated IPropertySheetEntry and enhanced the JavaDoc of
IPropertySheetEntry#resetPropertyValue to describe the behavior
when a default value is not meaningful.
Comment 25 Gunnar Wagenknecht CLA 2004-05-03 13:26:43 EDT
Please review, I'll create a patch for bug 54250 that will use the new API.
Comment 26 Pratik Shah CLA 2004-05-03 18:40:28 EDT
I have fixed SetPropertyValueCommand to handle this problem by checking the 
value of isPropertySet(String) before and after the new value is set.  So, as 
far as GEF is concerned, this is not a problem anymore.

There's probably no reason to include the new interface into this release, 
unless of course there are others who are affected by the same problem.
Comment 27 Nick Edgar CLA 2004-05-04 21:25:53 EDT
So there's nothing to do here?  Gunnar, do you agree that Pratik's workaround 
will suffice for 3.0?  Note that Friday is our API freeze.
Comment 28 Gunnar Wagenknecht CLA 2004-05-05 05:28:03 EDT
At least the JavaDoc should fixed. I'll rework the patch.
Comment 29 Tod Creasey CLA 2004-05-06 08:53:19 EDT
Nick has asked me to look to at this and submit something that is acceptable 
to both Gunnar and Randy as well as not breaking the existing API.

Gunnar and Randy what is your consensus on this. Are you still after the new 
interface?
Comment 30 Randy Hudson CLA 2004-05-06 10:30:37 EDT
I think both of us are really just concerned with the Undo/Redo scenario.  We 
have implemented Gunnar's suggestion, which is to call isPropertySet() before 
and after calling setProperty(..).  So there is no known scenario which 
requires the new interface to work properly.

However, it is too bad that the original interface is not perfect, but I think 
we can salvage it with some better JavaDoc and guidelines on how to treat 
isPropertySet(...) returning false.
Comment 31 Tod Creasey CLA 2004-05-06 11:05:08 EDT
Released Gunnars final patch and fixed the javadoc warnings in 
PropertySheetEntry.
Comment 32 Randy Hudson CLA 2004-08-03 14:48:03 EDT
The JavaDoc changes made to IPropertySource#isPropertySet(Object) are breaking 
API changes. And, it doesn't reflect the way 
PropertySheetEntry#resetPropertyValue() uses the API.

Pre-3.0: returning false indicates that the specified property does not have a 
default value
R3.0: returning true indicates that the specified property does not have a 
default property

The new R3.0 definition is correct *only* if you implement IPropertySource2, 
but otherwise it is incorrect.  If you implement only IPropertySource and a 
given property does not have a default value, then according to the API, you 
should return true.  But this means that the reset action on the propertysheet 
will get enabled, and resetProperty(Object) will be called on the 
IPropertySource.

So maybe we should restore the original API, and re-declare the method in 
IPropertySource2 stating the new definition.

Also, the DefaultsAction has never been smart about disabling.
Comment 33 Nick Edgar CLA 2005-04-28 15:54:46 EDT
Gunnar or Randy, do you think anything further needs to be done here for 3.1?
If so, if either of you could provide a patch, I'd really appreciate it.
Comment 34 Gunnar Wagenknecht CLA 2005-05-02 12:23:36 EDT
Created attachment 20599 [details]
New patch with corrected JavaDoc and interfaces

This patch corrects the API we broke in 3.0. It reverts the JavaDoc for
IPropertySource to the 2.1 contract and redefines it in IPropertySource2.
Comment 35 Nick Edgar CLA 2005-05-02 14:59:40 EDT
Thanks Gunnar.  I've asked the PMC to approve this API change.
Comment 36 Nick Edgar CLA 2005-05-02 15:23:28 EDT
Kevin gave the +1 for this.
Also need to update the plug-in migration guide for this API change.

Comment 37 Nick Edgar CLA 2005-05-04 14:01:50 EDT
Patch applied.
I've added the following to the Javadoc for IPropertySource2.isPropertySet:

     * <code>IPropertySource2</code> overrides the specification of this
<code>IPropertySource</code> 
     * method to return <code>true</code> instead of <code>false</code> if the
specified 
     * property does not have a meaningful default value.
     * <code>isPropertyResettable</code> will only be called if
<code>isPropertySet</code> returns
     * <code>true</code>.
Comment 38 Nick Edgar CLA 2005-05-04 14:24:07 EDT
I've added the following to the migration guide:

Changes to isPropertySet(boolean) in IPropertySource and IPropertySource2

What is affected: Plug-ins that implement
org.eclipse.ui.views.properties.IPropertySource or IPropertySource2.

Description: In Eclipse 3.0, the specification for the method
org.eclipse.ui.views.properties.IPropertySource.isPropertySet(boolean) was
incorrectly changed to specify that true should be returned if the specified
property did not have a meaningful default value. In previous versions, it
specified that false should be returned in this case. This was an inadvertent
breaking API change, although the implementation worked the same as before if
the property source implemented IPropertySource and not IPropertySource2. This
has been corrected in 3.1, with IPropertySource.isPropertySet(boolean) being
reverted back to its earlier specification (that false should be returned in
this case), and IPropertySource2.isPropertySet(boolean) overriding this to
specify that true should be returned in this case. For more details, see bug 21756.

Action required: Any classes implementing IPropertySource or IPropertySource2,
where some of the properties do not have meaningful default values, should be
checked to ensure that they return the appropriate value for
isPropertySource(boolean). Clients should check that the Restore Default Value
button in the Properties view works as expected for their property source.
Comment 39 Nick Edgar CLA 2005-05-04 14:24:55 EDT
cc'ing Jim for the API change.
Comment 40 Jim des Rivieres CLA 2005-05-04 16:52:36 EDT
approved - I'll add this one to the Annals of API Development :-)
Comment 41 Nick Edgar CLA 2005-05-10 15:26:29 EDT
Verified in I20050509-2010.