Changing the Starts With Filter in a Webtop 6.5 Object Locator into a Contains Filter(将查找对象对话框中的'以...开始'改为'包含')
http://www.revasolutions.com/ecm-blog/?p=40
Changing the Starts With Filter in a Webtop 6.5 Object Locator into a Contains Filter
October 5th, 2009 by Mark Chua
I’ve been working on some interesting and useful Webtop customizations for a client that I think many developers may find handy. One of them is customizing the locator component to use a contains filter instead of a starts with filter. The locator component is the component that lets you select one or more objects from a list. The screenshot depicts one such locator instance with the focus of our efforts encircled below. Now you’d expect this was easily configurable via xml, as did I, but you’ll quickly find that it’s actually not. However, it’s quite easily achieved via Java as I’ll soon show you.
First things first, you’ll need to have your development environment for webtop set up. It’ll be helpful to have access to some source files or at least be in possession of a handy decompiler like Cavaj. Now without further ado…
Firstly, you want make yourself an ObjectLocator. Since we’d rather not have to implement all the code for an abstract class (at least for this tutorial), we’ll just extend the PersistentObjectLocator and just override the methods that matter. It also turns out that the associated query class is what matters, so we’ll get right down to messing with the createQuery method. Copy the createQuery method right out of the PersistentObject.java source file [note: When navigating through the webtop directory structure maze, you'll find the locators in com.documentum.webcomponent.library.locator.]. To avoid the redundant pasting of code, I won’t post the code until after all of it is done. Since we are only going to make very few changes, it should be easy to see from there what the original was.
We pretty much only want to change the first line of the createQuery method. To do this, We can replace that line with a new instance of our own locator query extended from PersistentObjectLocatorQuery. That would come out to something like: PersistentObjectLocatorQuery query = new MyLocatorQuery();. Of course, we mustn’t forget to write the query class. I’ve already identified the important methods to copy and paste, which for our case is processNameStartsWith which you can find in the source for LocatorQuery. Once we fix this up we’ll actually be all set to go.
It turns out that m_clauseNameStartsWith is a private variable of LocatorQuery, but luckily for us, only this method ever uses it. Hence we can easily mimic how this variable was declared in LocatorQuery. While we’re at it, we might as well rename the variable to m_clauseNameContains. In fact, you could rename a lot of the local variables if you’d like. The code I’ll show later on will not rename anything. If we compile our code now, make the necessary configuration changes to point to our new MyLocator class, and test it, you’ll notice we have actually done nothing yet. Now all that’s left to do is to change Predicate.OBJ_SW to Predicate.OBJ_CO. That’ll do the trick. If you open up the Predicate you’ll see it has defined other constants that you could also use like Predicate.OBJ_EW and Predicate.OBJ_NC which corresponds to Ends With and Not Contains respectively.
You’ll notice that it doesn’t seem so elegant to have a method named processNameStartsWith that actually does something more on the lines of processNameContains, but it would take quite a bit more effort just to have the names match the functionality.
Here are the two classes we just worked on for your reference:
public class MyLocator extends PersistentObjectLocator { protected LocatorQuery createQuery() { PersistentObjectLocatorQuery query = new MyLocatorQuery(); // CHANGED THIS query.setViewDocbaseType(getInitialDocbaseType()); if(m_actualAttributes != null) { Vector attributeNames = new Vector(); Enumeration en = m_actualAttributes.elements(); while(en.hasMoreElements()) { AttributeObject attrObj = (AttributeObject) en.nextElement(); attributeNames.add(attrObj.getAttributeName()); } query.setDocbaseTypeAttributes(attributeNames); } return query; } } public class MyLocatorQuery extends PersistentObjectLocatorQuery { private Clause m_clauseNameStartsWith = null; protected void processNameStartsWith(String strAttributeName) { if (strAttributeName == null) { strAttributeName = "object_name"; } // name filter pattern String strNameStartsWith = getNameStartsWith(); // remove the previous name filter if (m_clauseNameStartsWith != null) { int idxNameStartsWith = m_vectWhereClauses.indexOf(m_clauseNameStartsWith); if (idxNameStartsWith > -1) { m_vectWhereClauses.remove(idxNameStartsWith); } } // add filter if (strNameStartsWith != null && strNameStartsWith.length() > 0) { StringExpression expNameLike = new StringExpression(LogicalOperator.OBJ_AND, strAttributeName, Predicate.OBJ_CO, strNameStartsWith); // CHANGED THIS addWhereClause(LogicalOperator.AND, expNameLike); m_clauseNameStartsWith = (Clause)m_vectWhereClauses.get(m_vectWhereClauses.size() -1); } } }
Those are the basics of how to get the contains functionality in your locator. Just put the correct class in your locator’s xml configuration. Of course you’d want to change the UI for it as well. In the properties file you can add an entry MSG_FILTER=Contains and then in MyLocator‘s onInit method you can set the tooltips:
PromptedText filterCtrl = (PromptedText)getControl(NAMEFILTERSTRING, PromptedText.class); filterCtrl.setToolTip(String); filterCtrl.getEnterButton().setToolTip(String);
Maybe you want the contains filter applied to another column. Again, there is no easy way to do this via xml, but you can certainly do it through Java. Look into the getViewStatement method of the query object and I’ll leave the details for another tutorial in the future. I hope this tutorial has been useful and I’m always open to suggestions if you know of a better method as well as corrections.