<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Please review and comment.<br><div><br><div>Begin forwarded message:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Helvetica" size="3" color="#000000" style="font: 12.0px Helvetica; color: #000000"><b>From: </b></font><font face="Helvetica" size="3" style="font: 12.0px Helvetica">Emmanuel Bernard <<a href="mailto:emmanuel.bernard@jboss.com">emmanuel.bernard@jboss.com</a>></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Helvetica" size="3" color="#000000" style="font: 12.0px Helvetica; color: #000000"><b>Date:<span class="Apple-converted-space"> </span></b></font><font face="Helvetica" size="3" style="font: 12.0px Helvetica"> June 17, 2009 14:41:03<span class="Apple-converted-space"> </span>EDT</font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Helvetica" size="3" color="#000000" style="font: 12.0px Helvetica; color: #000000"><b>To: </b></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "><font face="Helvetica" size="3" color="#000000" style="font: 12.0px Helvetica; color: #000000"><b>Subject: </b></font><font face="Helvetica" size="3" style="font: 12.0px Helvetica"><b>Re: Path, string or object model</b></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; min-height: 14px; "><br></div> </div><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Here is the solution I cooked. I think it's acceptable but add some complexity in the ConstraintValidatorContext API (see other email). Please review (pay special attention to the examples).<div><br></div><div>A Path represents the path and is the one accepted by the path consuming APIs. A Path is an Iterable of Nodes.</div><div><br></div><div><div>/**</div><div> * Represent a navigation path from an object to another.</div><div> * Each path element is represented by a Node.</div><div> *</div><div> * The path corresponds to the succession of nodes</div><div> * in the order they are retured by the Iterator</div><div> *</div><div> * @author Emmanuel Bernard</div><div> */</div><div>public interface Path extends Iterable<Node> {</div><div>}</div><div><br></div><div><br></div><div>A node represent a path element.</div><div><br></div><div><div>/**</div><div> * Represents an element of a navigation path</div><div> *</div><div> * @author Emmanuel Bernard</div><div> */</div><div>public interface Node {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>/**</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * Property name the node represents</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * or null if the leaf node and representing an entity</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * (in particular the node representing the root object</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * has its name null)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> */</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>String getName();</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>/**</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * True if the node represents an object contained in an Iterable</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * or in a Map.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> */</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>boolean isInIterable();</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>/**</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * The index the node is placed in if contained</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * in an array or List. Null otherwise.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> */</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>Integer getIndex();</div><div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>/**</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * The key the node is placed in if contained</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> * in a Map. Null otherwise.</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> */</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>Object getKey();</div><div>}</div><div><br></div><div>A few interesting points:</div><div> - the index / key is hosted by the node after the collection node</div><div><br></div><div>Here are a few examples and their Node equivalent</div><div><br></div><div>""</div><div>0: Node(name:null, isInIterable:false, index:null, key:null)</div></div><div><br></div><div><div><div>"email"</div><div>0: Node(name:email, isInIterable:false, index:null, key:null)</div><div><br></div><div><div><div>"addresses"</div><div>0: Node(name:addresses, isInIterable:false, index:null, key:null)</div><div><br></div><div><div><div>"addresses["home"]" represent the bean level of an Address object</div><div>0: Node(name:addresses, isInIterable:false, index:null, key:null)</div><div>1: Node(name:null, isInIterable:true, index:null, key:home)</div><div><br></div><div><div>"addresses["home"].city"</div><div>0: Node(name:addresses, isInIterable:false, index:null, key:null)</div><div>1: Node(name:city, isInIterable:true, index:null, key:home)</div><div><br></div></div></div></div><div><div>"billingAddresses[3].country.name"</div><div>0: Node(name:billingAddresses, isInIterable:false, index:null, key:null)</div><div>1: Node(name:country, isInIterable:true, index:3, key:null)</div><div>2: Node(name:name, isInIterable:false, index:null, key:null)</div><div><br></div><div><br></div><div>ConstraintViolation renders a Path</div><div><br></div><div>public interface ConstraintViolation<T> {</div><div> Path getPropertyPath();</div><div>}</div><div><br></div><div>TraversableResolver accepts a path</div><div><br></div><div>public interface TraversableResolver {</div><div><div><span class="Apple-tab-span" style="white-space:pre">        </span>boolean isReachable(Object traversableObject,</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span> String traversableProperty,</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span> Class<?> rootBeanType,</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span> Path pathToTraversableObject,</div><div><span class="Apple-tab-span" style="white-space:pre">                                                </span> ElementType elementType);</div><div> ...</div><div>}</div><div><br></div><div>PS: should String traversableProperty be Node traversableProperty ?</div></div></div></div></div><div><br></div></div></div><div><br><div><div>On May 27, 2009, at 12:19, Emmanuel Bernard wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">In several areas we do describe path:<div> - ConstraintViolation</div><div> - ConstraintValidatorContext (with addError(String, String) which allows to concatenate substrings</div><div><br></div><div>So far we use the notion of string to represent it</div><div> - address.name</div><div> - cards[3].color</div><div> - addresses["home"].city</div><div><br></div><div>I have added the idea of using [] for simple Iterable objects (ie non indexed, like a Set)</div><div> - accounts[].balance</div><div><br></div><div>Anybody objects to that?</div><div><br></div><div>Second point</div><div>Do we want to replace this String approach with a path object mode?</div><div><br></div><div><a href="http://opensource.atlassian.com/projects/hibernate/browse/BVAL-143">http://opensource.atlassian.com/projects/hibernate/browse/BVAL-143</a></div><div><font class="Apple-style-span" face="Arial">______</font></div><div><span class="Apple-style-span" style="font-family: Arial; ">path are today strings with dot separating properties. But it break when Set or Iterable are used. <br>We could replace that with <br>--- First strawman, must evolve -- <br>class PathElement { <br> String getName(); <br> PathElement getParentPath(); <br> boolean isIterable(); <br> boolean isIndexed(); <br> Object getIndex(); <br> //TODO int getIndex()? <br><br> // not happy about that as it is only useful for Constraintciolation <br> PathElement getChild(); <br>} <br><br>PathElement would be used for Constraintvuilation, maybe CVContext etc <br><br>can this be refactored using inheritance + generics to have an IndexedPathElement only when it matters (probably no unfortunately) </span></div><div><font class="Apple-style-span" face="Arial">______</font></div><div><font class="Apple-style-span" face="Arial"><br></font></div><div><br></div><div>Pros:</div><div> - less string manipulation by the user and the TraversableResolver implementation</div><div> - the map index no longer rely on "[" + toString() + "]" and is likely more easily handled</div><div><br></div><div>Cons:</div><div> - ConstraintValidatorContext becomes more complex as it needs to expose some kind of path element builder.</div><div> - we would like need to standardize some kind of String serialization anyway</div><div> - I don't see Pros as huge advantages</div><div><br></div><div>WDYT?</div></div></blockquote></div><br></div></div></div></blockquote></div><br></body></html>