My WorklistCriteria

  • 8 September 2008
  • 6 replies
  • 5 views

Badge +2

Hi everyone!


I'm trying to "wrap" WorklistCriteria class, to create "ad-hoc" filters.


Like SourceCode WorklistCriteria class, i've created 3 enums: AAField, AACompare, AALogical.


 AAField enum has got same members of WCField, plus one: WorklistItemMetadata (=30); this field contains the activity description (drawn from an XML file).


I've created a method: AAAddFilterField(AALogical, AAField, AACompare, Value)


My worklist is like this:


PROCESS_NAME - PROCESS_START_DATE - ACTIVITY_NAME - ACTIVITY_DESCRIPTION - ACTIVITY_START_DATE


I would like to create a filter with same behaviour of SourceCode WorklistCriteria, but insert a special filter method to ACTIVITY_DESCRIPTION field (example: if the user digits in a textbox "request", this method will show me all the activity description containing the word "request" in the string).


 


Could you help me?


Thanks a lot!


6 replies

Badge +4

I'm not sure I fully understand what you are attempting to do, but you aren't going to be able to substitute your own field enums, etc. into WorklistCriteria. No matter if you inherit from WorklistCriteria, etc., the code which is actually performing the comparison in the Client connection object and that isn't going to understand your new enum values.


What is wrapping the request going to provide which WorklistCriteria doesn't already?


 You can already filter on Activity Description like so:


SourceCode.Workflow.Client.

WorklistCriteria criteria = new SourceCode.Workflow.Client.WorklistCriteria();
criteria.AddFilterField(WCField.ActivityDescription, WCCompare.Like, "request");
Worklist wrklst = conn.OpenWorklist(criteria);


If that isn't sufficient, you'll probably have to bypass the SourceCode.Workflow.Client approach entirely and use SmartObjects to perform your queries.

Badge +2

Uhm...sorry...probably i've explained the problem in a wrong mode.


I've create a class, called MyWorklistCriteria class, like this:


public MyWorklistCriteria()


{


  ArrayList _wcFilter = new ArrayList();


}


private ArrayList _wcFilter;

public MyWCFilter[] WcFilter


{


  get { return (MyWCFilter[])this._wcFilter.ToArray(typeof(MyWCFilter)); }


}



public void MyFilterField(MyWCField Field, MyWCCompare Compare, Object Value) 


{


    this.MyFilterField(MyWCLogical.And, Field, Compare, Value);


}


public void MyFilterField(MyWCLogical Logical, MyWCField Field, MyWCCompare Compare, Object Value)


{


  MyWCFilter filter = null;


  MyWCLogical and;


  filter =

new MyWCFilter();


  if (this._wcFilter.Count != 0)


  and = Logical;


  else


  and =

MyWCLogical.And;


  filter.WcLogical = and;


  filter.WcField = Field;


  filter.WcCompare = Compare;


  filter.Value = Value;


  this._wcFilter.Add(filter);


}


 


My enums are the same of SourceCode.Workflow.Client WorklistCriteria enum, except MyWcField, which have one more field (WorklistItemMetadata = 40);


In my application, i check if the filter is a K2 filter (it occours when (int)MyWcField is less than 40): in this case i use WorklistCriteria:


SC.

WorklistCriteria scWorklistCriteria = new SC.WorklistCriteria();


foreach (MyWCFilter Myfilter in filterCriteria.WcFilter)


{


   if ((int)Myfilter.WcField < 100)


{


   SC.

WCField scField = (SC.WCField)Enum.Parse(typeof(SC.WCField), Enum.GetName(typeof(MyWCFilter), Myfilter.WcField), true);


   SC.

WCCompare scCompare = (SC.WCCompare)Enum.Parse(typeof(SC.WCCompare), Enum.GetName(typeof(MyWCCompare), Myfilter.WcCompare), true);


   SC.

WCLogical scLogical = (SC.WCLogical)Enum.Parse(typeof(SC.WCLogical), Enum.GetName(typeof(MyWCLogical), Myfilter.WcLogical), true);


   scWorklistCriteria.AddFilterField(scLogical, scField, scCompare, Myfilter.Value);


}


}


if (scWorklistCriteria.Filters.Length > 0)


   scWorklist = _k2Helper.K2Connection.OpenWorklist(scWorklistCriteria);


else


   scWorklist = _k2Helper.K2Connection.OpenWorklist();


 


But if it isn't a K2 filter i've to create a method who accept MyFilterCriteria and MyWorklist (SC.Worklist plus WorklistItemMetadata field) like this:


public Base.Worklist MyFilter(MyWorklistCriteria filterCriteria, Base.Worklist MyWorklist)


How to create this method to filter WorklistItemMetadata field too?


Thanks a lot!

Badge +4

Thanks, that's a much clearer explanation. Let me restate your scenario just to be sure we are on the same page:



  1. User creates your custom Criteria object passing in custom filters (many of which correspond one-to-one with K2 filters)
  2. Application checks the criteria object for any K2 supported filters and filters the user's worklist using the K2 Client API
  3. Application now has a partially filtered Worklist object which it needs to additionally filter against any custom filter types that didn't map one-to-one with the K2 filters.
  4. What is the best way to perform that filtering?

The answer is going to depend largely on what the additional data you need to filter against is and where it is coming from.


 So let's start with the basics which are probably going to be the same for all solutions:



  • You can't remove items from the Worklist collection, so you're going to have to create your own List<WorklistItem> to hold your filtered items.
  • You're going to have to iterate through each WorklistItem in Worklist, Open() it (assuming you need to access data from subobjects, etc), perform your additional filtering, and if the item passes, add it to your list.
  • Return the list.

That approach is going to have some performance considerations because Open() is a somewhat expensive call, so to the extent you can minimize those calls you'll be better off. Also, to the extent that you can make use of the NoData flag on the WorkflowCriteria object when filtering, you also may see some performance benefits.


So, some suggestions:



  • Don't overengineer the solution to start, iterate through the items, do your additional filtering, and see how it performs against your standard worklist size
  • If performance does seem slow then go back and attempt to optimize by

    • aggregate data calls for your external data
    • promote costly metadata fields to Process or Activity level fields so you can use K2's filtering (for example, if the data you want to filter against is in a 1 MB xml snippet and you have 100 worklist items on average, that's going to be pretty slow. Consider extracting the data out of the XML ahead of time, etc.)
    • restructure your external data so you can filter more effectively.
    • reverse the filtering order, try filtering against your external data first to obtain a list of IDs, Folios, etc., and then pass those into WorkflowCriteria to retrieve the WorklistItem list.
    • investigate alternative methods of filtering, such as using the reporting or workflow SmartObjects and the ADO.NET/SmartObjectClient APIs, direct DB queries (not supported), etc.

Again, this largely is going to depend on the particulars of your situation.


 HTH,

Badge +2

Thanks Colin,


really a careful and detailed answer. I'm trying to optimize performances.


One more question: i've read somewhere that AddFilterField method (i'm not interested to AddSortField method) is bug-afflicted.


Which kind of bug? I've read it will be fix in next patch (0807)...is it right?


Thanks again!

Badge +2

Thanks Colin,


really a careful and detailed answer. I'm trying to optimize performances.


One more question: i've read somewhere that AddFilterField method (i'm not interested to AddSortField method) is bug-afflicted.


Which kind of bug? I've read it will be fix in next patch (0807)...is it right?


Thanks again!


 


EDIT: sorry for double posting

Badge +4

The only bug I know of is the one specified in the KB article (http://kb.k2workflow.com/Articles/KB000218.aspx) which is supposed to be fixed in the 0803 release. That's not to say there aren't others, but that's the only one I know about.


 

Reply