My case is logically like this

Imagine these data structure

gamer:
userId
gameConsole
type

game:
gameId
gameName

A game is associated to a gameConsole
There are 2 types of gamers,
for a type = CASUAL gamer, there are no games associated
for a type = AVERAGE gamer, you can have games asscociated

Data as follows

userId: 1
gameConsole: nintendo
type: CASUAL

userId: 2
gameConsole: playstation
type: AVERAGE
gameId: 9, gameName: Gran Turismo
gameId: 10, gameName: Winning Eleven

Imagine I have a bean class called Wonky (that implements java.util.Map)
that behaves like this

Type = CASUAL
Wonky.get(String key) will return a Wonky instance, if you then call
getValue() on this instance it will return a gameConsole name (e.g.
nintendo or playstation)

Type = AVERAGE
Wonky.get(String key) will return a Wonky instance, if you then call
get(String key) on this instance it will return another Wonky instance, if
you then call getValue() on this instance it will return a game name (e.g
Gran Turismo or Winning Eleven)

I want to be able to do this on a form

<s:textfield name="wonky['1'].value"/>
During get: shows the gameConsole of gamer with userId = 1
During set: sets the gameConsole for gamer with userId = 1

<s:textfield name="wonky['1']['9'].value"/>
During get: shows the game with id = 9 associated with gamer with userId = 1
During set: set the game name with id = 9 associated with gamer with userId
= 1

alternatively, I'm ok with this idea as well

<s:textfield name="wonky['1'].value['9'].value"/>

In this case Wonky behaves like this for Type = AVERAGE

Wonky.get(String key) -> Wonky instance, getValue() -> return this;
get(String key) -> another Wonky instance, getValue() on that instance will
return a game name (e.g Gran Turismo or Winning Eleven)

I did more investigation

Consider this code

class MyMap implements Map {
 private Long id;

public MyMap(Long id) {
this.id = id;
}

...

@Override
public Object get(Object key) {
System.out.println("MyMap@" + id + ".get(" + key + ")");
return new MyMap(id + 1);
}

public String getValue() {
System.out.println("MyMap@" + id + ".getValue()");
return Long.toString(id);
}

public void setValue(String value) {
System.out.println("MyMap@" + id + ".setValue(" + value + ")");
}
}

On my action class

public MyMap getFieldMap() {
System.out.println(">> getFieldMap()");
MyMap map = new MyMap(1L);
return map;
}

public void setFieldMap(MyMap map) {
}

private Long index = 1L;

public Long getIndex() {
System.out.println(">> getIndex()");
return index;
}

public void setIndex(Long index) {
System.out.println(">> setIndex(" + index + ")");
this.index = index;
}

On my jsp

<s:form action="...">
<s:textfield name="fieldMap['%{index}']['%{index}'].value"/>
<s:submit/>
</s:form>

Result is

During get

>> getIndex()
>> getIndex()
>> getFieldMap()
my...@1.get(1)
my...@2.get(1)
my...@3.get(value)
>> getIndex()
>> getIndex()

Ok, getValue() isn't called, I can work with this, I can make all my keys
numbers, if I detect a non-number I just route the call to getValue()
I think since it implements a map, ".value" get interpreted as get("value");

During set

>> getFieldMap()
my...@1.get(1)
my...@2.get(1)

This I can't work with since setValue() isn't called anywhere.



On Tue, May 20, 2014 at 3:02 PM, Christoph Nenning <
christoph.nenn...@lex-com.net> wrote:

> > Question:
> > According to OGNL (
> > http://commons.apache.org/proper/commons-ognl/language-guide.html) under
> > heading JavaBeans Indexed Properties and OGNL Object Indexed Properties,
> > getFieldWithIndex(int index) should be called, but it isn't, same goes
> with
> >  getFieldWithKey(String key), why ?
> > I looked at the latest OGNL source code (not the one I'm using since I
> > couldn't find the source code for version 3.0.6) hoping if I could spot
> a
> > method where it tries different get/set methods.
> > Tried setting breakpoints at OGNLRuntime, ObjectPropertyAccessor but
> > coulnd't see anything obvious.
> >
> > At the moment I have a few workarounds
> > 1. Use the ones that are working, i.e. getFieldList() and getFieldMap(),
> > implementing my own List and Map
>
>
> Another way would be OGNL method call syntax:
>
> <s:property value="getFieldWithIndex(1)"/>
>
>
>
>
>
> > 2. Use java.util.List getList() and setList(java.util.List list), struts
> > will create a new List and populate accordingly in the order in which
> they
> > were submitted in the form
> > The issue with this is, if I have a pair or triplet of things that go
> hand
> > in hand, then it gets complex.
> > e.g.
> > name and address where address is optional
> > in the form the user put name1, address1, name2 (with no address), and
> > name3, address3
> > struts calls setName() with List containing name1, name2, name3
> > it also calls setAddress() with List containing address1, address3
> > There is no way the code can then figure out that that address3 is
> actually
> > associated with name3
> > In the past I was able to get around this by supplying another data
> > structure that tells the code which address belongs to which name but it
> > involves JavaScript, and it gets messy quite quickly.
>
>
>
> struts/OGNL can store mulitple values in a map. You could use name as key
> and address as value:
>
> address: <s:textfield name="map['name']" />
>
> That works well when you know names during "get phase" (when users cannot
> change names on that particular form).
> If users can also enter names here, you need javascript.
>
> Another use case of that map syntax is when the number of input fileds is
> dynamic.
>
>
>
>
> > 3. "Bypass" struts, in the "get" phase (showing the form) just use
> straight
> > html combined with struts tags, during the "set" phase (submitting the
> > form), will just get the parameters using HttpServletRequest
> > e.g. during show form
> > <input type="text" name="whateverName" value="<s:property
> > value="whateverValue"/>"/>
> > instead of
> > <s:textfield ... />
>
>
> This is always possible, of course. It means you have to generate
> parameter names during GET and parse them on POST.
>
> Usually I try to avoid this in my applications but there are (rare) cases
> I need to do that.
> If you do so, you have to think of how you do validation. You can still
> use struts validation when you generate the same parameter names again (in
> validate() method) and use <s:fieldError> tags with the same generated
> names.
>
>
>
>
>
> Regards,
> Christoph
>
>
>
>
>
>
> >
> > OGNL Indexed and Object Indexed Properties
> >
> > Hi,
> >
> > I'm wondering why this code is not working. I'm using struts 2.3.16.1
> and
> > ognl 3.0.6.
> >
> > In my action class I have this
> >
> > public String[] getFieldArray() {
> > System.out.println(">> getFieldArray()");
> > return null;
> > }
> >
> > public void setFieldArray(String[] array) {
> > }
> >
> > public MyList<String> getFieldList() {
> > System.out.println(">> getFieldList()");
> > return new MyList<String>();
> > }
> >
> > public void setFieldList(MyList<String> list) {
> > }
> >
> > public MyMap<String, String> getFieldMap() {
> > System.out.println(">> getFieldMap()");
> > return new MyMap<String, String>();
> > }
> >
> > public void setFieldMap(MyMap<String, String> map) {
> >
> > }
> >
> > public String getFieldWithIndex(int index) {
> > System.out.println(">> getFieldWithIndex(" + index + ")");
> > return null;
> > }
> >
> > public void setFieldWithIndex(int index, String value) {
> > System.out.println(">> setFieldWithIndex(" + index + "," + value + ")");
> > }
> >
> > public String getFieldWithKey(String key) {
> > System.out.println(">> getFieldWithKey(" + key + ")");
> > return null;
> > }
> >
> > public void setFieldWithKey(String key, String value) {
> > System.out.println(">> setFieldWithKey(" + key + "," + value + ")");
> > }
> >
> > Note that MyList and MyMap are as follows
> >
> > class MyMap<K, V> implements Map<K, V> { ... }
> > class MyList<V> implements List<V> { ... }
> >
> > I have the get() methods overridden on the those classes
> >
> > On my jsp I have this
> >
> > <s:property value="fieldArray[1]"/>
> > <s:property value="fieldList[1]"/>
> > <s:property value="fieldMap['1']"/>
> > <s:property value="fieldWithIndex[1]"/>
> > <s:property value="fieldWithKey['1']"/>
> >
> > Result is
> >
> > >> getFieldArray()
> > >> getFieldList()
> > MyList.get(1)
> > >> getFieldMap()
> > MyMap.get(1)
> > MyMap.get(1)
> >
> > Question:
> > According to OGNL (
> > http://commons.apache.org/proper/commons-ognl/language-guide.html) under
> > heading JavaBeans Indexed Properties and OGNL Object Indexed Properties,
> > getFieldWithIndex(int index) should be called, but it isn't, same goes
> with
> >  getFieldWithKey(String key), why ?
> > I looked at the latest OGNL source code (not the one I'm using since I
> > couldn't find the source code for version 3.0.6) hoping if I could spot
> a
> > method where it tries different get/set methods.
> > Tried setting breakpoints at OGNLRuntime, ObjectPropertyAccessor but
> > coulnd't see anything obvious.
> >
> > At the moment I have a few workarounds
> > 1. Use the ones that are working, i.e. getFieldList() and getFieldMap(),
> > implementing my own List and Map
> >
> > 2. Use java.util.List getList() and setList(java.util.List list), struts
> > will create a new List and populate accordingly in the order in which
> they
> > were submitted in the form
> > The issue with this is, if I have a pair or triplet of things that go
> hand
> > in hand, then it gets complex.
> > e.g.
> > name and address where address is optional
> > in the form the user put name1, address1, name2 (with no address), and
> > name3, address3
> > struts calls setName() with List containing name1, name2, name3
> > it also calls setAddress() with List containing address1, address3
> > There is no way the code can then figure out that that address3 is
> actually
> > associated with name3
> > In the past I was able to get around this by supplying another data
> > structure that tells the code which address belongs to which name but it
> > involves JavaScript, and it gets messy quite quickly.
> >
> > 3. "Bypass" struts, in the "get" phase (showing the form) just use
> straight
> > html combined with struts tags, during the "set" phase (submitting the
> > form), will just get the parameters using HttpServletRequest
> > e.g. during show form
> > <input type="text" name="whateverName" value="<s:property
> > value="whateverValue"/>"/>
> > instead of
> > <s:textfield ... />
>
> This Email was scanned by Sophos Anti Virus
>

Reply via email to