Re: How (not) to: IModel and Collections (and generics)
Thanks for your reply. I think I can (at least partially) understand your position and think there aren't any new arguments here I can mention. So the discussions seems to be at an end here. Maybe it is a matter of taste... If I find any time, I will create a patch... Regards, Johannes On Sat, 2009-03-07 at 12:40 -0800, Igor Vaynberg wrote: you are right, the components that just read a collection do just that, read it. they simply ignore the setter method in imodel. no big deal, just because you are given an interface doesnt mean you have to use all the methods in it. thus abstractreadonlymodel. however, a lot of components manipulate items in the collection. you are right, they can do this without ever needing a setter, but it is very convenient to have a callback that lets you know that the collection has been updated. it is even more convenient to have a callback be part of model itself because in wicket you often factor out conversions and other transformations into the model implementation itself so they are reusable across multiple components. keep in mind models are the glue between components and your domain model, so if any kind of massaging needs to be done for the domain model to work smoothly with the component the model is the perfect place to do it. -igor On Sat, Mar 7, 2009 at 12:25 PM, Johannes Schneider maili...@cedarsoft.com wrote: i think misuse is a pretty bold word considering you are talking to people who designed and built imodel, dont you think? :) Well, I think you are right. Sorry for that. I just mean, that it has a bad smell here... if we do what you suggest then we would end up with: interface imodel { object getobject(); } interface icollectionmodel extends imodel { object convert(object); } interface iwhatevermodel extends imodel { void setobject(object); } then things that are built on top of imodel now have to be built on top of at least two hierarchies (imodel and iwhatevermodel - considering icollectionmodel can be a mixin which all implementations have to check for which makes it dirty), so we will end up with double the classes like loadabledetachablemodel, etc. Yes, I think we need at least two interfaces. I don't know whether we need the icollectionmodel... I think that can be discussed. where as right now this works perfectly and is quiet elegant: abstract class collectionconverternew,old implements imodelcollectionnew { private final imodelcollectionold delegate; public collectionnew getobject() { listnew list=new arraylistnew(delegate.getobject().size()); for (old o:delegate.getobject()) { list.add(converttonew(o)); } return list; } public void setobject(collectionnew object) { delegate.getobject().clear(); for (new o:object) { delegate.getobject().add(converttold(o)); } } abstract new converttonew(old o); abstract old converttoold(new o); } Don't know, whether that is really elegant. It feels more like a misuse... ;). I think there is a reason you don't simply take an object for everything (what might be the most elegant)... I really don't understand why IModel must handle the conversion stuff. That conversion thing could/should be done using some wrapper or something else. But I don't get all the concepts of Wicket. I just think that components that just *read* a collection, should just read the collection... But well, as you mentioned correctly, you have designed it, so it is your choice... Regards, Johannes -igor Regards, Johannes -igor On Wed, Mar 4, 2009 at 4:50 AM, Johannes Schneider maili...@cedarsoft.com wrote: Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping
Re: How (not) to: IModel and Collections (and generics)
On Wed, 2009-03-04 at 09:14 -0800, Igor Vaynberg wrote: components that deal with collections in wicket always reuse the same instance of collection is one was provided where it makes sense. Yes, and therefore a setter is not necessary. setobject is still called on the model, but is called with the same instance of collection. this is necessary so that if you have a model that translates a collection of one type to a collection of another can perform the conversion when the component pushes new data into it. And this is just a *misuse* of the given method... Why not create a own model interface for collections and add some sort of conversion method/object? Regards, Johannes -igor On Wed, Mar 4, 2009 at 4:50 AM, Johannes Schneider maili...@cedarsoft.com wrote: Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping class for that case. But this case is not very common. Maybe someone finds a good example - I can't. For the other two cases it does *not* make any sense to call IModel#setObject. Summary: Nearly in every case when the IModel contains a collection, the setObject method does not make any sense and must not be called. Conclusion: I think we should have created some sort of IModelProvider (contains only the getObject method) and IModel (with both methods). Components that just *read* values from the model, accept the read only interface now. For special cases where a magic component adds/removes elements to a collection, we need some sort of ICollectionModel that offers add and remove methods (but no setter). That interface - of course - will be based upon a collection *without* wildcards... Regards, Johannes Schneider - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: How (not) to: IModel and Collections (and generics)
On Sat, Mar 7, 2009 at 10:15 AM, Johannes Schneider maili...@cedarsoft.com wrote: setobject is still called on the model, but is called with the same instance of collection. this is necessary so that if you have a model that translates a collection of one type to a collection of another can perform the conversion when the component pushes new data into it. And this is just a *misuse* of the given method... Why not create a own model interface for collections and add some sort of conversion method/object? i think misuse is a pretty bold word considering you are talking to people who designed and built imodel, dont you think? :) if we do what you suggest then we would end up with: interface imodel { object getobject(); } interface icollectionmodel extends imodel { object convert(object); } interface iwhatevermodel extends imodel { void setobject(object); } then things that are built on top of imodel now have to be built on top of at least two hierarchies (imodel and iwhatevermodel - considering icollectionmodel can be a mixin which all implementations have to check for which makes it dirty), so we will end up with double the classes like loadabledetachablemodel, etc. where as right now this works perfectly and is quiet elegant: abstract class collectionconverternew,old implements imodelcollectionnew { private final imodelcollectionold delegate; public collectionnew getobject() { listnew list=new arraylistnew(delegate.getobject().size()); for (old o:delegate.getobject()) { list.add(converttonew(o)); } return list; } public void setobject(collectionnew object) { delegate.getobject().clear(); for (new o:object) { delegate.getobject().add(converttold(o)); } } abstract new converttonew(old o); abstract old converttoold(new o); } -igor Regards, Johannes -igor On Wed, Mar 4, 2009 at 4:50 AM, Johannes Schneider maili...@cedarsoft.com wrote: Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping class for that case. But this case is not very common. Maybe someone finds a good example - I can't. For the other two cases it does *not* make any sense to call IModel#setObject. Summary: Nearly in every case when the IModel contains a collection, the setObject method does not make any sense and must not be called. Conclusion: I think we should have created some sort of IModelProvider (contains only the getObject method) and IModel (with both methods). Components that just *read* values from the model, accept the read only interface now. For special cases where a magic component adds/removes elements to a collection, we need some sort of ICollectionModel that offers add and remove methods (but no setter). That interface - of course - will be based upon a collection *without* wildcards... Regards, Johannes Schneider - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: How (not) to: IModel and Collections (and generics)
i think misuse is a pretty bold word considering you are talking to people who designed and built imodel, dont you think? :) Well, I think you are right. Sorry for that. I just mean, that it has a bad smell here... if we do what you suggest then we would end up with: interface imodel { object getobject(); } interface icollectionmodel extends imodel { object convert(object); } interface iwhatevermodel extends imodel { void setobject(object); } then things that are built on top of imodel now have to be built on top of at least two hierarchies (imodel and iwhatevermodel - considering icollectionmodel can be a mixin which all implementations have to check for which makes it dirty), so we will end up with double the classes like loadabledetachablemodel, etc. Yes, I think we need at least two interfaces. I don't know whether we need the icollectionmodel... I think that can be discussed. where as right now this works perfectly and is quiet elegant: abstract class collectionconverternew,old implements imodelcollectionnew { private final imodelcollectionold delegate; public collectionnew getobject() { listnew list=new arraylistnew(delegate.getobject().size()); for (old o:delegate.getobject()) { list.add(converttonew(o)); } return list; } public void setobject(collectionnew object) { delegate.getobject().clear(); for (new o:object) { delegate.getobject().add(converttold(o)); } } abstract new converttonew(old o); abstract old converttoold(new o); } Don't know, whether that is really elegant. It feels more like a misuse... ;). I think there is a reason you don't simply take an object for everything (what might be the most elegant)... I really don't understand why IModel must handle the conversion stuff. That conversion thing could/should be done using some wrapper or something else. But I don't get all the concepts of Wicket. I just think that components that just *read* a collection, should just read the collection... But well, as you mentioned correctly, you have designed it, so it is your choice... Regards, Johannes -igor Regards, Johannes -igor On Wed, Mar 4, 2009 at 4:50 AM, Johannes Schneider maili...@cedarsoft.com wrote: Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping class for that case. But this case is not very common. Maybe someone finds a good example - I can't. For the other two cases it does *not* make any sense to call IModel#setObject. Summary: Nearly in every case when the IModel contains a collection, the setObject method does not make any sense and must not be called. Conclusion: I think we should have created some sort of IModelProvider (contains only the getObject method) and IModel (with both methods). Components that just *read* values from the model, accept the read only interface now. For special cases where a magic component adds/removes elements to a collection, we need some sort of ICollectionModel that offers add and remove methods (but no setter). That interface - of course - will be based upon a collection *without* wildcards... Regards, Johannes Schneider - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail:
Re: How (not) to: IModel and Collections (and generics)
you are right, the components that just read a collection do just that, read it. they simply ignore the setter method in imodel. no big deal, just because you are given an interface doesnt mean you have to use all the methods in it. thus abstractreadonlymodel. however, a lot of components manipulate items in the collection. you are right, they can do this without ever needing a setter, but it is very convenient to have a callback that lets you know that the collection has been updated. it is even more convenient to have a callback be part of model itself because in wicket you often factor out conversions and other transformations into the model implementation itself so they are reusable across multiple components. keep in mind models are the glue between components and your domain model, so if any kind of massaging needs to be done for the domain model to work smoothly with the component the model is the perfect place to do it. -igor On Sat, Mar 7, 2009 at 12:25 PM, Johannes Schneider maili...@cedarsoft.com wrote: i think misuse is a pretty bold word considering you are talking to people who designed and built imodel, dont you think? :) Well, I think you are right. Sorry for that. I just mean, that it has a bad smell here... if we do what you suggest then we would end up with: interface imodel { object getobject(); } interface icollectionmodel extends imodel { object convert(object); } interface iwhatevermodel extends imodel { void setobject(object); } then things that are built on top of imodel now have to be built on top of at least two hierarchies (imodel and iwhatevermodel - considering icollectionmodel can be a mixin which all implementations have to check for which makes it dirty), so we will end up with double the classes like loadabledetachablemodel, etc. Yes, I think we need at least two interfaces. I don't know whether we need the icollectionmodel... I think that can be discussed. where as right now this works perfectly and is quiet elegant: abstract class collectionconverternew,old implements imodelcollectionnew { private final imodelcollectionold delegate; public collectionnew getobject() { listnew list=new arraylistnew(delegate.getobject().size()); for (old o:delegate.getobject()) { list.add(converttonew(o)); } return list; } public void setobject(collectionnew object) { delegate.getobject().clear(); for (new o:object) { delegate.getobject().add(converttold(o)); } } abstract new converttonew(old o); abstract old converttoold(new o); } Don't know, whether that is really elegant. It feels more like a misuse... ;). I think there is a reason you don't simply take an object for everything (what might be the most elegant)... I really don't understand why IModel must handle the conversion stuff. That conversion thing could/should be done using some wrapper or something else. But I don't get all the concepts of Wicket. I just think that components that just *read* a collection, should just read the collection... But well, as you mentioned correctly, you have designed it, so it is your choice... Regards, Johannes -igor Regards, Johannes -igor On Wed, Mar 4, 2009 at 4:50 AM, Johannes Schneider maili...@cedarsoft.com wrote: Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping class for that case. But this case is not very common. Maybe someone finds a good example - I can't. For the other two cases it does *not* make any sense to call IModel#setObject. Summary: Nearly in every case when the IModel contains a collection, the setObject method does not make any sense and must not be called. Conclusion: I think we should have created some sort of IModelProvider (contains only the getObject method) and
How (not) to: IModel and Collections (and generics)
Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping class for that case. But this case is not very common. Maybe someone finds a good example - I can't. For the other two cases it does *not* make any sense to call IModel#setObject. Summary: Nearly in every case when the IModel contains a collection, the setObject method does not make any sense and must not be called. Conclusion: I think we should have created some sort of IModelProvider (contains only the getObject method) and IModel (with both methods). Components that just *read* values from the model, accept the read only interface now. For special cases where a magic component adds/removes elements to a collection, we need some sort of ICollectionModel that offers add and remove methods (but no setter). That interface - of course - will be based upon a collection *without* wildcards... Regards, Johannes Schneider - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: How (not) to: IModel and Collections (and generics)
Does AbstractReadOnlyModel accomplish what you're talking about? Scott On Wed, Mar 4, 2009 at 4:50 AM, Johannes Schneider maili...@cedarsoft.com wrote: Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping class for that case. But this case is not very common. Maybe someone finds a good example - I can't. For the other two cases it does *not* make any sense to call IModel#setObject. Summary: Nearly in every case when the IModel contains a collection, the setObject method does not make any sense and must not be called. Conclusion: I think we should have created some sort of IModelProvider (contains only the getObject method) and IModel (with both methods). Components that just *read* values from the model, accept the read only interface now. For special cases where a magic component adds/removes elements to a collection, we need some sort of ICollectionModel that offers add and remove methods (but no setter). That interface - of course - will be based upon a collection *without* wildcards... Regards, Johannes Schneider - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: How (not) to: IModel and Collections (and generics)
components that deal with collections in wicket always reuse the same instance of collection is one was provided where it makes sense. setobject is still called on the model, but is called with the same instance of collection. this is necessary so that if you have a model that translates a collection of one type to a collection of another can perform the conversion when the component pushes new data into it. -igor On Wed, Mar 4, 2009 at 4:50 AM, Johannes Schneider maili...@cedarsoft.com wrote: Hi, the concept of IModel seems to be very obvious. It is simply some kind of reference and offers a getter and a setter. When used with ordinary object, everything works fine. An IModel that contains a String can easily be mapped to a TextField. The text field calls getObject to show the initial value and sets the changed string to the model using setObject on form commit. Everything becomes a little more complicated when collections are affected. The problem is, that it is not obvious what those collections represent. 1) A collection might be read-only (e.g. the possible choices for a selection). 2) But it also might be necessary to add/remove single elements (e.g. privileged users shown within a shuffle list). 3) And sometimes the complete collection is changed (can't find an example here). IModel only supports the *third* method where the complete collection is replaced. (Don't forget that the reference to the collection changes which will lead to several other problems.) I strongly recommend the usage of a wrapping class for that case. But this case is not very common. Maybe someone finds a good example - I can't. For the other two cases it does *not* make any sense to call IModel#setObject. Summary: Nearly in every case when the IModel contains a collection, the setObject method does not make any sense and must not be called. Conclusion: I think we should have created some sort of IModelProvider (contains only the getObject method) and IModel (with both methods). Components that just *read* values from the model, accept the read only interface now. For special cases where a magic component adds/removes elements to a collection, we need some sort of ICollectionModel that offers add and remove methods (but no setter). That interface - of course - will be based upon a collection *without* wildcards... Regards, Johannes Schneider - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org