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/