Improving the SRDemo Shuttle Adapter
Monday, 11. June 2007, 14:03:32
In the ADF Developer's Guide and in the SRDemo sample application, there is a backing bean class to help populate a SelectManyShuttle component from two tables with a foreign key association.
This is already fairly flexible as you can specify the underlying value, the label and even a description attribute for each item that is retrieved. There is a level of flexibility that is missing though, and that is the ability to specify more than one attribute to serve as the label (or description).
Say you wanted to be able to assign several employees to a project using the shuttle adapter as backing for a SelectOneShuttle component. You would obviously choose the EmployeeId as the value attribute, but what attribute would you choose for the label? Either FirstName or LastName is likely to be repeated, but a combination of both (with maybe another attribute in the description to differentiate employees with the exact same name) would make it much easier to select the correct employee.
It is actually fairly simple to modify the existing shuttle backing described in the Developer's Guide. The end result of this being that you can specify the allItemsDisplayAttrName attribute in the following form:
where any word that resolves to an attribute name in the row will be replaced by the value of that attribute, and any other charaters will stay as they are. So this example might give you a list of employees looking like this:
The work for this is done in the ShuttlePageBackingBeanBase class and in the getAllItems method. Before we do anything, it looks like this:
I've replaced this code completely with my own, but you could easily move it into the ADFUtils so as to make this generic for anywhere that uses the selectItemsForIterator method.
Here's the modified method:
This code finds the specified iterator, then extracts the attribute definitions. From there it uses a regular expression match to find if the attribute name is used in either the display or description strings. If an attribute is found, it is stored for later use.
The code then iterates through each of the rows in the iterator and then uses the stored attribute names to do a global replace on the strings with the actual values from the current row.
I hope this is simple enough not to need an example project. If you have any questions, just pop a reply in here and I can get back to you.
This is already fairly flexible as you can specify the underlying value, the label and even a description attribute for each item that is retrieved. There is a level of flexibility that is missing though, and that is the ability to specify more than one attribute to serve as the label (or description).
Say you wanted to be able to assign several employees to a project using the shuttle adapter as backing for a SelectOneShuttle component. You would obviously choose the EmployeeId as the value attribute, but what attribute would you choose for the label? Either FirstName or LastName is likely to be repeated, but a combination of both (with maybe another attribute in the description to differentiate employees with the exact same name) would make it much easier to select the correct employee.
It is actually fairly simple to modify the existing shuttle backing described in the Developer's Guide. The end result of this being that you can specify the allItemsDisplayAttrName attribute in the following form:
LastName, FirstName
where any word that resolves to an attribute name in the row will be replaced by the value of that attribute, and any other charaters will stay as they are. So this example might give you a list of employees looking like this:
Abel, Ellen Ande, Sundar Atkinson, Mozhe Austin, David Baer, Hermann Baida, Shelli Banda, Amit Bates, Elizabeth Bell, Sarah etc.
The work for this is done in the ShuttlePageBackingBeanBase class and in the getAllItems method. Before we do anything, it looks like this:
public List getAllItems() {
if (allItems == null) {
allItems = ADFUtils.selectItemsForIterator(allItemsIteratorName,
allItemsValueAttrName,
allItemsDisplayAttrName,
allItemsDescriptionAttrName);
}
return allItems;
}I've replaced this code completely with my own, but you could easily move it into the ADFUtils so as to make this generic for anywhere that uses the selectItemsForIterator method.
Here's the modified method:
public List getAllItems() {
if (allItems == null) {
allItems = new ArrayList();
ArrayList attrNameList = new ArrayList();
DCIteratorBinding iter = ADFUtils.findIterator(allItemsIteratorName);
AttributeDef[] attrDefs = iter.getAttributeDefs();
for (int i = 0; i < attrDefs.length; i++)
{
AttributeDef attrDef = attrDefs[i];
String attrName = attrDef.getName();
if (allItemsDisplayAttrName.matches(".*\\b" + attrName + "\\b.*") ||
allItemsDescriptionAttrName.matches(".*\\b" + attrName + "\\b.*"))
{
attrNameList.add(attrName);
}
}
for (Row r: iter.getAllRowsInRange())
{
for (int i = 0; i < attrNameList.size(); i++)
{
String attrName = (String)attrNameList.get(i);
allItemsDisplayAttrName = allItemsDisplayAttrName.replace(attrName,
r.getAttribute(attrName).toString());
allItemsDescriptionAttrName = allItemsDescriptionAttrName.replace(attrName,
r.getAttribute(attrName).toString());
}
allItems.add(new SelectItem(r.getAttribute(allItemsValueAttrName),
allItemsDisplayAttrName,
allItemsDescriptionAttrName));
}
}
return allItems;
}This code finds the specified iterator, then extracts the attribute definitions. From there it uses a regular expression match to find if the attribute name is used in either the display or description strings. If an attribute is found, it is stored for later use.
The code then iterates through each of the rows in the iterator and then uses the stored attribute names to do a global replace on the strings with the actual values from the current row.
I hope this is simple enough not to need an example project. If you have any questions, just pop a reply in here and I can get back to you.
how do i get ADFUtils class?
By anonymous user, # 21. April 2008, 22:00:19
By dominionspy, # 23. April 2008, 16:11:32