Finding Items

Now that SMTK 3.1 is in the process of being released, I’m looking at improving how you find attribute items within an attribute.

For searching Attributes, SMTK 3.1 provides the following methods:

  • ItemPtr Attribute::find(const std::string &name, SearchStyle)
  • ItemPtr Attribute::itemAtPath(const std::string& path, const std::string& seps);

For searching Group Items, SMTK 3.1 provides the following methods:

  • smtk::attribute::ItemPtr GroupItem::find(const std::string& inName) - looks at the first subgroup
  • smtk::attribute::ItemPtr GroupItem::find(std::size_t element, const std::string& name);

For searching ValueItems, SMTK 3.1 provides the following methods:

  • ItemPtr ValueItem::findChild(const std::string& name, smtk::attribute::SearchStyle);

Note that most of these methods also have const counterparts as well as versions that will auto dynamic cast the returned item to the appropriate type

Search Style is an enum consisting of the following values:

  • NO_CHILDREN - when searching a value item search all of the items who are direct children of the value item regardless of whether they are active or not
  • ALL_CHILDREN - when searching a value item search all of the items who are direct children as well as their descendants regardless of whether they are active or not
  • ACTIVE_CHILDREN - when searching a value item search only the active items who are direct children as well as their descendants iff they are considered active as well

Note that there is no common find method in the attribute::Item class so many of these find methods need to explicitly cast items to GroupItem or ValueItem to use their appropriate find methods. This design makes it difficult to add new classes of Items that have internal children items you may wish to search so I am proposing the following changes:

  • Add a ItemPtr Item::findDescendant(const std::string& name, smtk::attribute::SearchStyle)
  • Redefine the Search Style enum to have the following:
    • ACTIVE_CHILDREN (value x00) - when searching a value item search only the active items who are direct children
    • ALL_CHILDREN (value x01) - when searching a value item search all of the items who are direct children of the value item regardless of whether they are active or not (what NO_CHILDREN use to mean)
    • ACTIVE_DESCENDANTS (value x02) - when searching a value item search only the active items who are direct children as well as their descendants iff they are considered active as well (what ACTIVE_CHILDREN use to mean)
    • ALL_DESCENDANTS (value 0x3) - when searching a value item search all of the items who are direct children as well as their descendants regardless of whether they are active or not (what ALL_CHILDREN use to mean)

Note that the enum has a bit field structure - bit 0 : All or Active, bit 1: Immediate Children Only or All Descendants

I would suggest keeping the existing SearchStyle enums but adding these synonyms (ordered from the most narrow search to the most broad search):

  • IMMEDIATE_ACTIVE - only return a direct child of the item if it is active and the name matches.
  • IMMEDIATE_EXTANT - return any direct, extant child with the given name, regardless of whether it is active.
  • RECURSIVE_ACTIVE - return the first child found recursively (in a breadth-first search) that is also active.
  • RECURSIVE_EXTANT - return the first child found recursively (in a breadth-first search) whose name matches.

Parsing the two search-style proposals above:

  • I am inclined to prefer the terms immediate/recursive over children/descendants.
  • But I am NOT enthusiastic about either active/all or active/extant.

And trying to stir things up further … Would anyone consider changing the semantics in this discussion from “search style” to “search filters”? From that perspective, I would like to propose yet another strawman:

  • If no filter argument is specified, then the query is recursive for all descendants.
  • If filter options are specified, they can be used to limit the query to either or both of two constants that I’ll call IMMEDIATE and/or ACTIVE. (So we still cover the 4 search styles as I understand them.)
  • I am NOT convinced this is a better approach, but I think an argument in its favor is that this filter pattern is used in SQL syntax. (Well, actually SQL is more general than this…)

@johnt I am not wild about multiple signatures; that makes programmatic iteration over different searches painful. What about these enum values:

  • IMMEDIATE_ACTIVE
  • IMMEDIATE
  • RECURSIVE_ACTIVE
  • RECURSIVE

Well gee, if the only downside of a filter argument is the function signature, we can always add “filters=NONE” as the default arg.

As for the 4 enums David offered, I can live with them.

And since I generally work in python, I can always add my own findItem() method to wrap the C++ method with whatever signature I prefer there.

After another IRL convo with Bob, I thought I should document what I think is the go-forward plan, at least, what I said I can live with.

  1. Bob will do all the work (nice)
  2. Update the SearchStyle enum to include 4 new values (IMMEDIATE_ACTIVE, IMMEDIATE, RECURSIVE_ACTIVE, RECURSIVE). I’ll add a table below to indicate what I believe is the correct mapping is from the current values, but please let me know any corrections are required.
  3. Update the findChild() method in GroupItem and ValueItem classes to recognize the new enum and implement the new logic for the new mode, which I think is IMMEDIATE_ACTIVE.
  4. As for providing a default search style argument, Bob and I didn’t discuss that, but I would vote to omit any default value for now, and instead make the user explicitly state their requirement.
  5. MAYBE at some point in time (smtk 4.0?), drop the 3 original enum names.
  6. Later, update the Attribute::itemAtPath() method to use the same enum, with some caveat that the “recursive” values aren’t applicable and, I suppose, will be interpreted as their corresponding “immediate” values. And again, I would vote for no default search style, at least for now.
Current New
ACTIVE_CHILDREN RECURSIVE_ACTIVE
ALL_CHILDREN RECURSIVE
NO_CHILDREN IMMEDIATE
(not supported) IMMEDIATE_ACTIVE