Tjaart van Wijck wrote:
> Guillaume,
> 
> That worked! Thanks a lot for the help.
> 
> Yet, I still don't understand why the HQL string below does not yield
> the correct results:
> $query = "select obj from BaseObject obj where
> obj.className='Contacts.ContactClass'"
> 
> Can someone explain how XWiki traverses documents and objects to
> generate the resultset when executing HQL statements?

$xwiki.selectDocuments is a "safe" method, because it allows to select 
only document names. $xwiki.search is a "privileged" method, because it 
allows a user to retrieve ANYTHING from the database, even data he might 
not have access to, like private documents or user emails or passwords 
(fortunately the passwords are not stored in plaintext in the database, 
so that is not an issue, but simple passwords could be cracked using 
brute force dictionary attacks). For this reason $xwiki.search requires 
programming rights, and is not the recommended method for retrieving 
information.

This is why your query does not work:

$xwiki.search("select obj from BaseObject obj...") will return what you 
told it to select: instances of BaseObject, which is the privileged 
com.xpn.xwiki.objects.BaseObject class, privileged as in "it should not 
be exposed to the scripting world". However, since you're already using 
a privileged method to retrieve them, that is not a problem by itself 
anymore. But these objects have different methods than the object API 
which is regularly used in velocity scripts, located in 
com.xpn.xwiki.api.Object, so $item.get does not work because it is not a 
method of that object. When you see that a method that is supposed to 
work doesn't, like was the case with your $item.get, then either the 
object is null, or has a different type than you expect it to be. What 
you should do in this case is try to see what's wrong, and you do this 
by writing:

$item $item.class

This will print either $item, if it is null, or something for $item 
followed by the real class name. You then go to that class documentation 
and see what you should use. So a working script would be:

#set($query="select obj from BaseObject obj where 
obj.className='Contacts.ContactClass'")
#set($results=$xwiki.search($query, 10, 1))
#foreach ($item in $results)
#set($item = $item.newObjectApi($item, $context.context))
$item.get("firstname") | $item.get("surname") | $item.get("phone1") <br />
#end


or:

#set($query="select obj from BaseObject obj where
obj.className='Contacts.ContactClass'")
#set($results=$xwiki.search($query, 10, 1))
#foreach ($item in $results)
$item.displayView("firstname", $context.context) | 
$item.displayView("surname", $context.context) | 
$item.displayView("phone1", $context.context) <br />
#end

Either one of these is NOT recommended, as they require programming 
rights. The proper way is:

#set($query=", BaseObject obj where obj.name = doc.fullName and 
obj.className='Contacts.ContactClass' and obj.name <> 
'Contacts.ContactClassTemplate'")
## Replace with the real name of your template document, if there is one
#set($results=$xwiki.searchDocuments($query, 10, 1))
#foreach ($docName in $results)
   #set($docItem = $xwiki.getDocument($docName))
   #foreach($item in $docItem.getObjects("Contacts.ContactClass))
     $docItem.display("firstname", $item) | $docItem.display("surname", 
$item) | $docItem.display("phone1", $item) <br />
   #end
#end

This is different from the other suggested scripts because it does not 
assume that there is only one object in each document, but it iterates 
over each object of that type.
-- 
Sergiu Dumitriu
http://purl.org/net/sergiu/

_______________________________________________
users mailing list
users@xwiki.org
http://lists.xwiki.org/mailman/listinfo/users

Reply via email to