cancel
Showing results for 
Search instead for 
Did you mean: 

customising advanced search

netos
Champ in-the-making
Champ in-the-making
hi

we would like to add additional options to advanced search, and we did so as explaned in the Wiki, except that when we selected a custom attribute to search against, it decided to show it as a drop down choice while we are interested in a multiple choice component.

any suggestions?

thx, netanel.
6 REPLIES 6

kevinr
Star Contributor
Star Contributor
The Advanced Search UI will render the most appropriate component depending on the attribute type and the constraint. I don't believe it supports multi-value attributes for this though - you will have to raise an enhancement request in JIRA.

Thanks,

Kevin

netos
Champ in-the-making
Champ in-the-making
i figured it out.
i changed the component type from UISelectOne to UISelectMany, and with some little modifications it works.
thx anyway

claudio_martins
Champ in-the-making
Champ in-the-making
It would be great if you could post to the community what are these "little modifications" you've mentioned. Smiley Happy


Cheers, CM.

netos
Champ in-the-making
Champ in-the-making
sure, no problems. was just waiting to see if it interests someone at all… Smiley Very Happy

in the class UISearchCustomProperties in method generateControl(FacesContext, PropertyDefinition, String, String) i changed the component type in the else clause (~ line 402) i changed the component type from UISelectOne to UISelectMany. this only causes the app to crash when trying to go to advanced search screen since the ValueBinding for UISelectMany expects a list on any rendering attempt, while alfresco returns null on first rendering attempt. that required changing the field customProperties in class AdvancedSearchBean from HashMap to MyHashMap, a simple modified map which extends HashMap and returns an empty list instead of null when a request for the ValueBinding arrives.



public class MyHashMap<T1, T2> extends HashMap<T1, Object> {

   @Override
   public Object get(Object key) {
      
      Object result = super.get(key);
      
         if(result == null){
            if(key instanceof String){
               if(((String)key).contains
                        (UISearchCustomProperties.PREFIX_LOV_ITEM))
           return new LinkedList<String>();
            }
            else
   return result;
         }
      
         return result;
   }
   
   public MyHashMap(int i, float f) {
      super(i, f);
   }
}


now, i had to change the method search in the same bean in order to reflect the change. ~ line 876



else if (value != null)
{
    Object item = this.customProperties.get(
                     UISearchCustomProperties.PREFIX_LOV_ITEM + qname);
    if (item != null && !(item instanceof LinkedList))
    {
       // ListOfValues
       if (((Boolean)value) == true)
       {
           if(item instanceof ArrayList){ // just for the safe side
              search.addListValueQuery(QName.createQName(qname),
                                                        (ArrayList<String>)item);
           }
           else //we actually never get here
              search.addFixedValueQuery(QName.createQName(qname),
                                                           item.toString());
       }
    }
    else…//left unchanged


in MyHashMap it's important to return LinkedList since JSF returns ArrayList and that is needed to differentiate between multiple selection types and other types which do not have ValueBinding. (getting LinkedList is equivalent to getting null as you can see in MyHashMap.)

finally, i had to add to SearchContext the method addListValueQuery and the appropriate field - Map<QName, ArrayList<String>> queryListValues
as similiar to queryAttributes for example.

the appropriate change in method buildQuery(int) is the addition of:



if (queryListValues.size() != 0)
{
   for (QName qname : queryListValues.keySet())
   {
       flagSearchedProperty(qname);
       String escapedName = Repository.escapeQName(qname);
       ArrayList<String> valuesList = queryListValues.get(qname);
       if(valuesList.size() != 0){
          if (attributeQuery == null)
          {
             attributeQuery = new StringBuilder(queryListValues.size() << 6);
           }
           attributeQuery.append(" +(");
           for(Iterator<String> iter = valuesList.iterator() ; iter.hasNext() ; )
          {
               String value = iter.next();
               attributeQuery.append("@").append(escapedName)
                          .append(":\"").append(value).append('"');
               if(iter.hasNext())
                  attributeQuery.append(" OR ");
           }
           attributeQuery.append(")");
       }
    }
}


that's it. any further questions will be welcomed.

gilles
Champ in-the-making
Champ in-the-making
As we would like to do the minimum modifications in the classes, I wondering if it is still not possible to configure a multiple choice in a customized advanced-search.jsp. For example we would like to let the user chose to restrict his search to some types; or to search only for some countries in a country list.
Is there any no-build-needed  solution? (in 2.1 and/or 2.9?)

gavinc
Champ in-the-making
Champ in-the-making
I don't believe so, the best thing to do is to raise an enhancement request in JIRA.