Forum OpenACS Development: XoTCL: Find objects based on slot value

How do I find objects based on a slot value in XoTCL?

And more specifically, how do I find all multivalued slots of a class?

And how do I get a list of identifiers (not names, but IDs which are again a slot of the slot) for those multivalued slots?

At the moment I help myself by setting a multival_attr_ids parameter in the class, storing upon initialization or change of the class the multivalue ids. But obviously this is a cludge.

And maybe I should ask these kind of questions on the XoTCL Mailinglist ....

Collapse
Posted by Stefan Sobernig on
Mmmh. You can devise manifold "language query" mechanisms ...


How do I find objects based on a slot value in XoTCL?
Class Person -slots {
  Attribute first_name
  Attribute last_name
  Attribute jobs -multivalued true
  Attribute tasks -multivalued true
}

Person instforward expr -objscope ::expr

Person proc @ {attribute {operator eq} value} { if {[my info slots $attribute] eq ""} return; set results [list] foreach i [my info instances -closure] { if {[$i exists $attribute]} { if {[expr "\"[$i $attribute]\" $operator \"$value\""]} { lappend results $i } } } return $results }

Person new -first_name Malte -last_name Sussdorff Person new -first_name Gustaf -last_name Neumann Person new -first_name Stefan -last_name Sobernig Person new -first_name Gustaf -last_name "von Neumann"

puts [Person @ first_name eq Gustaf]


And more specifically, how do I find all multivalued slots of a class?

set multivalued_slots [list]
foreach s [Person info slots] {
  if {[$s multivalued]} {
    lappend multivalued_slots $s
  }
}
puts $multivalued_slots


And how do I get a list of identifiers (not names, but IDs which are again a slot of the slot) for those multivalued slots?

I don't quite get what you want to achieve here, maybe it is answered above ...

Collapse
Posted by Gustaf Neumann on
Here is a small implementation of an XOTcl based query 
language that i posted a few years ago to the XOTcl mailing
list. It is slightly adapted to XOTcl 1.6.* and more 
general than Stefan's example, since one can use
arbitrary expressions over arbitrary classes.

Note that instead of iterating over all instances of the 
classes (see info instances below), it is possible to build
one or multiple indices that can reduce the number of 
objects to be tested significantly.

The output of the script below is:

   C select {$x > 10} --> {::c2 ::d1} 
   C select {$x >= 10} --> {::c1 ::c2 ::d1 ::d2}
   C select {$x < 1} --> {}
   C select {[string match *00* $x]} --> {::d1}

all the best
-gustaf neumann


##############################################################
#
# Small query language for XOTcl Objects (part 1)
# 
# Gustaf Neumann fecit, Sept 2005
#
# In this example, we define a method select, which
# can be used to select arbitrary objects from the
# database based on a "select" expression.
#
##############################################################
# 1) Define method expr for all Objects, the operands are taken 
#     from the instance variables

Object instforward expr -objscope

# 2) Define method select with some arbitrary Tcl expression. All objects,
#    for which the expression returns 1 are returned

Class instproc select {expr} {
  set result_list [list]
  foreach o [my info instances -closure] {
    if {![catch [list $o expr $expr] result]} {
      if {$result} {
    lappend result_list $o
      }
    } else {
      puts "error in expr $expr for object $o -> $result"
    }
  }
  return $result_list
}

# Ok, we are done.
# We define a few sample classes and objects with some instance variables

Class C -parameter {{x 10}}
Class D -superclass C

C c1 
C c2 -x 11
D d1 -x 100
D d2


# Finally, we try it out with some demo queries.
#
# A query of the form 
#   <classname> select <expression>
# returns
#   ... all instances of the specified class
#   (or one of its subclasses) for which expression
#   is true.
#

# Examples: 
foreach q {
  {$x > 10} 
  {$x >= 10} 
  {$x < 1} 
  {[string match *00* $x]}
} {
  puts "C select [list $q] --> {[lsort [C select $q]]}\n"
}