Scarab commit: svn commit: r10445 - trunk/src: conf/classes conf/conf java/org/tigris/scarab/actions java/org/tigris/scarab/actions/base java/org/tigris/scarab/attribute java/org/tigris/scarab/feeds java/org/tigris/scarab/om java/org/tigris/scarab/reports java/org/tigris/scarab/screens java/org/tigris/scarab/screens/admin java/org/tigris/scarab/search java/org/tigris/scarab/tools java/org/tigris/scarab/tools/localization java/org/tigris/scarab/util java/org/tigris/scarab/util/word java/org/tigris/scarab/xmlrpc test/org/tigris/scarab/feeds test/org/tigris/scarab/test test/org/tigris/scarab/util test/org/tigris/scarab/util/word webapp/WEB-INF/templates/macros webapp/WEB-INF/templates/screens webapp/WEB-INF/templates/screens/help webapp/WEB-INF/templates/snippets

[email protected]
Newsgroups gmane.comp.java.scarab.cvs
Message-ID <[email protected]>
Author: ronvoe122
Date: 2007-06-09 08:06:34-0700
New Revision: 10445

Added:
   trunk/src/java/org/tigris/scarab/search/
   trunk/src/java/org/tigris/scarab/search/CachedQuery.java
   trunk/src/java/org/tigris/scarab/search/CachedResultList.java
Removed:
   trunk/src/java/org/tigris/scarab/util/SubsetIterator.java
   trunk/src/java/org/tigris/scarab/util/SubsetIteratorWithSize.java
   trunk/src/java/org/tigris/scarab/util/word/ComplexQueryException.java
   trunk/src/test/org/tigris/scarab/util/SubsetIteratorTest.java
   trunk/src/test/org/tigris/scarab/util/SubsetIteratorWithSizeTest.java
   trunk/src/webapp/WEB-INF/templates/screens/help/UserQueryComplex.vm
   trunk/src/webapp/WEB-INF/templates/snippets/ComplexQueryHelpLink.vm
Modified:
   trunk/src/conf/classes/ScarabBundle_de.properties
   trunk/src/conf/classes/ScarabBundle_en.properties
   trunk/src/conf/conf/TurbineResources.properties
   trunk/src/conf/conf/intake.xml
   trunk/src/java/org/tigris/scarab/actions/ConfigureIssueList.java
   trunk/src/java/org/tigris/scarab/actions/ConfigureReport.java
   trunk/src/java/org/tigris/scarab/actions/ReportIssue.java
   trunk/src/java/org/tigris/scarab/actions/Search.java
   trunk/src/java/org/tigris/scarab/actions/base/RequireLoginFirstAction.java
   trunk/src/java/org/tigris/scarab/attribute/DateAttribute.java
   trunk/src/java/org/tigris/scarab/feeds/QueryFeed.java
   trunk/src/java/org/tigris/scarab/om/Attribute.java
   trunk/src/java/org/tigris/scarab/om/AttributeValue.java
   trunk/src/java/org/tigris/scarab/om/Issue.java
   trunk/src/java/org/tigris/scarab/om/RModuleUserAttribute.java
   trunk/src/java/org/tigris/scarab/reports/ReportBridge.java
   trunk/src/java/org/tigris/scarab/screens/IssueList.java
   trunk/src/java/org/tigris/scarab/screens/IssueListExport.java
   trunk/src/java/org/tigris/scarab/screens/admin/ViewXMLExportIssues.java
   trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java
   trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java
   trunk/src/java/org/tigris/scarab/util/ScarabConstants.java
   trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java
   trunk/src/java/org/tigris/scarab/util/word/IssueSearchFactory.java
   trunk/src/java/org/tigris/scarab/util/word/QueryResult.java
   trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java
   trunk/src/java/org/tigris/scarab/xmlrpc/SimpleHandler.java
   trunk/src/test/org/tigris/scarab/feeds/QueryFeedTest.java
   trunk/src/test/org/tigris/scarab/test/AllScarabTests.java
   trunk/src/test/org/tigris/scarab/util/word/IssueSearchTest.java
   trunk/src/webapp/WEB-INF/templates/macros/AdvancedQueryMacro.vm
   trunk/src/webapp/WEB-INF/templates/macros/GlobalMacros.vm
   trunk/src/webapp/WEB-INF/templates/screens/IssueList.vm
   trunk/src/webapp/WEB-INF/templates/screens/Search.vm
   trunk/src/webapp/WEB-INF/templates/screens/ViewIssue.vm
   trunk/src/webapp/WEB-INF/templates/screens/help/UserQuery.vm

Log:
Reworked search functionality (major simplification and some new features) 
* requires heavy testing! 
* developer visible changes
   * create sql query using Torques Criteria objects instead of sql strings
   * don't keep a connection open across method calls
   * use one sql query to get the result list and the size of the list if possible
   * just query for issue ids and get all other display values using the existing methods of the Issue class. 
   * cache the result of the last query in each session
   * use lists instead of custom "iterators with size"
   * moved some logic from the velocity templates into the java classes
   ...
   * removed various bugs
   * added new bugs (hopefully not to much)
* user visible changes
   * [SCB525] sort by issue type
   * sort by module
   * [SCB2233] query by last modification time 
   * [SCB54] query by logged on user (eg. my open issues) 
   * [SCB1679] query by relative dates (eg. issues changed in the last three days
   * use the list of issues returned by the query 
     when viewing the single issues and using the previous and next links (dont query the database again).
   * ...


Modified: trunk/src/conf/classes/ScarabBundle_de.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_de.properties?view=diff&rev=10445&p1=trunk/src/conf/classes/ScarabBundle_de.properties&p2=trunk/src/conf/classes/ScarabBundle_de.properties&r1=10444&r2=10445
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_de.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_de.properties	2007-06-09 08:06:34-0700
@@ -618,6 +618,7 @@
 IssueIDQuery=Ticketnummernabfrage
 IssueIDRange=Ticketnummernauswahl
 CreationDateRange=Zeitraum für Ticket-Erstellungsdatum
+ChangeDateRange=Zeitraum für Ticket-Änderungsdatum
 DateRange=Datumsbereich
 DateEg=(z.B. {0})
 CommonAttributes=Allgemeine Attribute

Modified: trunk/src/conf/classes/ScarabBundle_en.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/classes/ScarabBundle_en.properties?view=diff&rev=10445&p1=trunk/src/conf/classes/ScarabBundle_en.properties&p2=trunk/src/conf/classes/ScarabBundle_en.properties&r1=10444&r2=10445
==============================================================================
--- trunk/src/conf/classes/ScarabBundle_en.properties	(original)
+++ trunk/src/conf/classes/ScarabBundle_en.properties	2007-06-09 08:06:34-0700
@@ -678,6 +678,7 @@
 IssueIDQuery=Issue ID query
 IssueIDRange=Issue ID range
 CreationDateRange=Issue creation date range
+ChangeDateRange=Issue change date range
 DateRange=Date range
 DateEg=(e.g. {0})
 CommonAttributes=Common Attributes

Modified: trunk/src/conf/conf/TurbineResources.properties
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/conf/TurbineResources.properties?view=diff&rev=10445&p1=trunk/src/conf/conf/TurbineResources.properties&p2=trunk/src/conf/conf/TurbineResources.properties&r1=10444&r2=10445
==============================================================================
--- trunk/src/conf/conf/TurbineResources.properties	(original)
+++ trunk/src/conf/conf/TurbineResources.properties	2007-06-09 08:06:34-0700
@@ -811,16 +811,3 @@
 template.TemplateList.vm.noIssueTypesForwardsTo=IssueTypeList.vm
 template.admin/XMLExportIssues.vm.noIssueTypesForwardsTo=IssueTypeList.vm
 template.admin/XMLImportIssues.vm.noIssueTypesForwardsTo=IssueTypeList.vm
-
-
-#Mysql's (at least, other db's not tested) query optimizer cannot handle more
-#than about 12 inner joins before it exponentially increases the time spent
-#calculating the query plan.  The exact number where this becomes a problem
-#is a function of how long users can be expected to wait as well as how many
-#issues are in the db.  The number of total joins is also important, though
-#the outer joins used in Query do not appear to be as expensive.  These numbers
-#are relatively conservative.
-scarab.report.max.criteria=4
-scarab.query.max.filter_criteria=9
-scarab.query.max.join=30
-

Modified: trunk/src/conf/conf/intake.xml
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/conf/conf/intake.xml?view=diff&rev=10445&p1=trunk/src/conf/conf/intake.xml&p2=trunk/src/conf/conf/intake.xml&r1=10444&r2=10445
==============================================================================
--- trunk/src/conf/conf/intake.xml	(original)
+++ trunk/src/conf/conf/intake.xml	2007-06-09 08:06:34-0700
@@ -310,15 +310,21 @@
         </field>
         <field name="CommentQuery" key="cq" type="String">
         </field>
+        <field name="MergePartialTextQueries" key="mptq" type="boolean">
+        </field>
         <field name="MinId" key="lid" type="String">
            <rule name="mask" value="^[0-9]{1,9}$|^[A-Za-z]{0,4}[0-9]{1,9}$">intake_InvalidIssueId</rule>
         </field>
         <field name="MaxId" key="hid" type="String">
            <rule name="mask" value="^[0-9]{1,9}$|^[A-Za-z]{0,4}[0-9]{1,9}$">intake_InvalidIssueId</rule>
         </field>
-        <field name="MinDate" key="ld" type="String">
+        <field name="MinCreationDate" key="lcrd" type="String">
+        </field>
+        <field name="MaxCreationDate" key="hcrd" type="String">
+        </field>
+        <field name="MinChangeDate" key="lchd" type="String">
         </field>
-        <field name="MaxDate" key="hd" type="String">
+        <field name="MaxChangeDate" key="hchd" type="String">
         </field>
         <field name="StateChangeAttributeId" key="scai" type="int"/>
         <field name="StateChangeFromOptionId" key="scfoi" type="int"/>

Modified: trunk/src/java/org/tigris/scarab/actions/ConfigureIssueList.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/ConfigureIssueList.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/actions/ConfigureIssueList.java&p2=trunk/src/java/org/tigris/scarab/actions/ConfigureIssueList.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/actions/ConfigureIssueList.java	(original)
+++ trunk/src/java/org/tigris/scarab/actions/ConfigureIssueList.java	2007-06-09 08:06:34-0700
@@ -186,6 +186,9 @@
 	            }
 	        }
         }
+        
+        scarabR.clearCachedQueryResult();
+        
         doCancel(data,context);
     }
 

Modified: trunk/src/java/org/tigris/scarab/actions/ConfigureReport.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/ConfigureReport.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/actions/ConfigureReport.java&p2=trunk/src/java/org/tigris/scarab/actions/ConfigureReport.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/actions/ConfigureReport.java	(original)
+++ trunk/src/java/org/tigris/scarab/actions/ConfigureReport.java	2007-06-09 08:06:34-0700
@@ -46,15 +46,12 @@
  * individuals on behalf of Collab.Net.
  */ 
 
-import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.commons.collections.MapIterator;
-import org.apache.commons.collections.map.LinkedMap;
 import org.apache.commons.lang.StringUtils;
 import org.apache.fulcrum.intake.Intake;
 import org.apache.fulcrum.intake.model.Group;
@@ -260,11 +257,9 @@
             //searchGroup.setProperties(search);
 
             // Set attribute values to search on
-            LinkedMap avMap = search.getCommonAttributeValuesMap();
-            for (MapIterator i = avMap.mapIterator(); i.hasNext();) 
+            for (Iterator i = search.getAttributeValuesMap(true).values().iterator(); i.hasNext();) 
             {
-            	i.next();
-                AttributeValue aval = (AttributeValue)i.getValue();
+                AttributeValue aval = (AttributeValue)i.next();
                 Group group = intake.get("AttributeValue", aval.getQueryKey());
                 if (group != null) 
                 {
@@ -272,8 +267,7 @@
                 }                
             }
             
-            // remove unset AttributeValues
-            List setAttValues = removeUnsetValues(search.getAttributeValues());
+            List setAttValues = search.getSetAttributeValues();
             
             ReportHeading heading = report.getReportDefinition()
                 .getAxis(axis).getHeading(level);
@@ -390,27 +384,6 @@
         L10NMessage msg = new L10NMessage(key);
         return msg.getMessage(l10n);
     }
-
-    /**
-     * remove unset AttributeValues. this method is c/p from IssueSearch
-     *
-     * @param attValues a <code>List</code> value
-     */
-    private List removeUnsetValues(List attValues)
-    {
-        int size = attValues.size();
-        List setAVs = new ArrayList(size);
-        for (int i=0; i<size; i++) 
-        {
-            AttributeValue attVal = (AttributeValue) attValues.get(i);
-            if (attVal.getOptionId() != null || attVal.getValue() != null
-                 || attVal.getUserId() != null) 
-            {
-                setAVs.add(attVal);
-            }
-        }
-        return setAVs;
-    }
         
     /**
      * Adds users to the current header.
@@ -1056,7 +1029,6 @@
         {
             report.setDefaultDate(null);
         }
-        ScarabLocalizationTool l10n = getLocalizationTool(context);
         scarabR.setConfirmMessage(L10NKeySet.ChangesSaved);
         setTarget(data, "reports,ConfineDataset.vm");
     }

Modified: trunk/src/java/org/tigris/scarab/actions/ReportIssue.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/ReportIssue.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/actions/ReportIssue.java&p2=trunk/src/java/org/tigris/scarab/actions/ReportIssue.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/actions/ReportIssue.java	(original)
+++ trunk/src/java/org/tigris/scarab/actions/ReportIssue.java	2007-06-09 08:06:34-0700
@@ -53,7 +53,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.StringTokenizer;
 
 import org.apache.commons.collections.MapIterator;
 import org.apache.commons.collections.map.LinkedMap;
@@ -67,7 +66,6 @@
 import org.tigris.scarab.attribute.DateAttribute;
 import org.tigris.scarab.attribute.OptionAttribute;
 import org.tigris.scarab.attribute.UserAttribute;
-import org.tigris.scarab.notification.NotificationManager;
 import org.tigris.scarab.notification.NotificationManagerFactory;
 import org.tigris.scarab.om.ActivitySet;
 import org.tigris.scarab.notification.ActivityType;
@@ -87,10 +85,8 @@
 import org.tigris.scarab.tools.ScarabRequestTool;
 import org.tigris.scarab.tools.localization.L10NKeySet;
 import org.tigris.scarab.tools.localization.L10NMessage;
-import org.tigris.scarab.util.IteratorWithSize;
 import org.tigris.scarab.util.Log;
 import org.tigris.scarab.util.ScarabConstants;
-import org.tigris.scarab.util.word.ComplexQueryException;
 import org.tigris.scarab.util.word.IssueSearch;
 import org.tigris.scarab.util.word.IssueSearchFactory;
 import org.tigris.scarab.util.word.MaxConcurrentSearchException;
@@ -227,47 +223,26 @@
             return true;
         }
 
-        // search on the option attributes and keywords
-        IssueSearch search = null;
         String template = null;
         boolean dupThresholdExceeded = false;
+        IssueSearch duplicateSearch = IssueSearchFactory.INSTANCE.getInstance(issue, (ScarabUser)data.getUser());
         try 
         {
-            search = IssueSearchFactory.INSTANCE.getInstance(issue, (ScarabUser)data.getUser());
-            // remove special characters from the text attributes
-            for (Iterator textAVs = search.getTextAttributeValues().iterator(); textAVs.hasNext();)
-            {
-                AttributeValue av = (AttributeValue)textAVs.next();
-                if (av.getAttribute().getAttributeType().getName().equals("date"))
-                    av.setValue(DateAttribute.internalDateFormat(av.getValue(), getLocalizationTool(context).get(L10NKeySet.ShortDatePattern)));
-                String s = av.getValue();
-                if (s != null && s.length() > 0) 
-                {
-                    StringTokenizer tokens = new StringTokenizer(s, 
-                        ScarabConstants.INVALID_SEARCH_CHARACTERS);
-                    StringBuffer query = new StringBuffer(s.length() + 10);
-                    while (tokens.hasMoreTokens())
-                    {
-                        query.append(' ');
-                        query.append(tokens.nextToken());
-                    }
-                    av.setValue(query.toString().toLowerCase());       
-                }
-            }
-        
-            // set the template to dedupe unless none exist, then skip
-            // to final entry screen
-            IteratorWithSize queryResults = search.getQueryResults();
-            dupThresholdExceeded = (queryResults.size() > threshold);
+            duplicateSearch.setLocalizationTool(getLocalizationTool(context));
+            duplicateSearch.removeSpecialCharacters();
+            
+            List possibleDuplicates = duplicateSearch.getQueryResults();
+            dupThresholdExceeded = possibleDuplicates.size() > threshold;
             if (dupThresholdExceeded)
             {
-                List matchingIssueIds = new ArrayList(maxResults);
-                // limit the number of matching issues to maxResults
-                for (int i = 0; queryResults.hasNext() && i <= maxResults; i++) 
+                List possibleDuplicateIds = new ArrayList(maxResults);
+                Iterator resultsIterator = possibleDuplicates.iterator();
+
+                for (int i = 0; resultsIterator.hasNext() && i <= maxResults; i++) 
                 {
-                    matchingIssueIds.add(((QueryResult)queryResults.next()).getUniqueId());
+                    possibleDuplicateIds.add(((QueryResult)resultsIterator.next()).getUniqueId());
                 }
-                context.put("issueList", matchingIssueIds);
+                context.put("issueList", possibleDuplicateIds);
                 template = "entry,Wizard2.vm";
             }
             else
@@ -280,16 +255,10 @@
             getScarabRequestTool(context).setInfoMessage(
                 L10NKeySet.DupeCheckSkippedForLackOfResources);            
         }
-        catch (ComplexQueryException e)
-        {
-            getScarabRequestTool(context).setInfoMessage(
-                    L10NKeySet.DupeCheckSkippedBecauseComplexity);            
-        }
         finally
         {
-            if (search != null) 
+            if (duplicateSearch != null) 
             {
-                search.close();
                 IssueSearchFactory.INSTANCE.notifyDone();
             }
         }

Modified: trunk/src/java/org/tigris/scarab/actions/Search.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/Search.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/actions/Search.java&p2=trunk/src/java/org/tigris/scarab/actions/Search.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/actions/Search.java	(original)
+++ trunk/src/java/org/tigris/scarab/actions/Search.java	2007-06-09 08:06:34-0700
@@ -48,10 +48,12 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.fulcrum.intake.Intake;
@@ -86,13 +88,11 @@
 import org.tigris.scarab.tools.ScarabRequestTool;
 import org.tigris.scarab.tools.localization.L10NKeySet;
 import org.tigris.scarab.tools.localization.L10NMessage;
-import org.tigris.scarab.util.IteratorWithSize;
 import org.tigris.scarab.util.Log;
 import org.tigris.scarab.util.ScarabConstants;
 import org.tigris.scarab.util.ScarabUtil;
 import org.tigris.scarab.util.export.ExportFormat;
 import org.tigris.scarab.util.word.IssueSearch;
-import org.tigris.scarab.util.word.IssueSearchFactory;
 
 /**
  *  This class is responsible for searching.
@@ -119,7 +119,7 @@
     ScarabRequestTool scarabR;
     Intake intake;
     ParameterParser params;
-    ScarabUser user;
+    public ScarabUser user;
 
     /**
      *
@@ -128,152 +128,147 @@
         throws Exception
     {
         setup(data, context);
-        IteratorWithSize queryResults = scarabR.getCurrentSearchResults();
-        if (queryResults != null && queryResults.hasNext())
-        {
-            context.put("queryResults", queryResults);
-            String next = ScarabUtil.findValue(data, "next");
-            if (StringUtils.isNotEmpty
-                (ScarabUtil.findValue(data, ExportFormat.KEY_NAME)))
-            {
-                // Send to the IssueListExport screen (which actually
-                // has no corresponding Velocity template).
-                setTarget(data, "IssueListExport.vm");
-            }
-            else if (StringUtils.isNotEmpty(next))
-            {
-                // Redirect to View, Assign, or Move/Copy
-                List issueIds = null;
-                ScarabUser user = (ScarabUser) data.getUser();
-                if (next.indexOf("All") > -1)
-                {
-                    // all issues are selected
-                    issueIds = getAllIssueIds(data);
-                }
-                else
-                {
-                    // get issues select by user
-                    issueIds = getSelected(data);
-                }
+        String next = ScarabUtil.findValue(data, "next");
+        if (StringUtils.isNotEmpty
+            (ScarabUtil.findValue(data, ExportFormat.KEY_NAME)))
+        {
+            // Send to the IssueListExport screen (which actually
+            // has no corresponding Velocity template).
+            setTarget(data, "IssueListExport.vm");
+        }
+        else if (StringUtils.isNotEmpty(next))
+        {
+            // Redirect to View, Assign, or Move/Copy
+            List issueIds = null;
+            ScarabUser user = (ScarabUser) data.getUser();
+            if (next.indexOf("All") > -1)
+            {
+                // all issues are selected
+                issueIds = getAllIssueIds(data);
+            }
+            else
+            {
+                // get issues select by user
+                issueIds = getSelected(data);
+            }
 
 
-                if (issueIds.size() < 1)
-                {
-                    scarabR.setAlertMessage(L10NKeySet.SelectIssues);
-                    return;
-                }
+            if (issueIds.size() < 1)
+            {
+                scarabR.setAlertMessage(L10NKeySet.SelectIssues);
+                return;
+            }
 
-                List modules = ModuleManager.getInstancesFromIssueList(
-                    scarabR.getIssues(issueIds));
-                if (next.indexOf("assign") > -1)
+            List modules = ModuleManager.getInstancesFromIssueList(
+                scarabR.getIssues(issueIds));
+            if (next.indexOf("assign") > -1)
+            {
+                if (user.hasPermission(ScarabSecurity.ISSUE__ASSIGN, modules))
                 {
-                    if (user.hasPermission(ScarabSecurity.ISSUE__ASSIGN, modules))
+                    if (issueIds.size() <= ScarabConstants.ISSUE_MAX_ASSIGN)
                     {
-                        if (issueIds.size() <= ScarabConstants.ISSUE_MAX_ASSIGN)
-                        {
-                            scarabR.resetAssociatedUsers();
-                            setTarget(data, "AssignIssue.vm");
-                        }
-                        else
-                        {
-                            L10NMessage msg = new L10NMessage
-                            (
-                                L10NKeySet.IssueLimitExceeded,
-                                String.valueOf(ScarabConstants.ISSUE_MAX_ASSIGN)
-                            );
-                            scarabR.setAlertMessage(msg);
-                            return;
-                        }
+                        scarabR.resetAssociatedUsers();
+                        setTarget(data, "AssignIssue.vm");
                     }
                     else
                     {
-                        scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                        L10NMessage msg = new L10NMessage
+                        (
+                            L10NKeySet.IssueLimitExceeded,
+                            String.valueOf(ScarabConstants.ISSUE_MAX_ASSIGN)
+                        );
+                        scarabR.setAlertMessage(msg);
                         return;
                     }
                 }
-                else if (next.indexOf("view") > -1)
+                else
+                {
+                    scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                    return;
+                }
+            }
+            else if (next.indexOf("view") > -1)
+            {
+                if (user.hasPermission(ScarabSecurity.ISSUE__VIEW, modules))
                 {
-                    if (user.hasPermission(ScarabSecurity.ISSUE__VIEW, modules))
+                    if (issueIds.size() <= ScarabConstants.ISSUE_MAX_VIEW)
                     {
-                        if (issueIds.size() <= ScarabConstants.ISSUE_MAX_VIEW)
-                        {
-                            setTarget(data, "ViewIssueLong.vm");
-                        }
-                        else
-                        {
-                            L10NMessage msg = new L10NMessage
-                            (
-                                L10NKeySet.IssueLimitExceeded,
-                                String.valueOf(ScarabConstants.ISSUE_MAX_VIEW)
-                            );
-                            scarabR.setAlertMessage(msg);
-                            return;
-                        }
+                        setTarget(data, "ViewIssueLong.vm");
                     }
                     else
                     {
-                        scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                        L10NMessage msg = new L10NMessage
+                        (
+                            L10NKeySet.IssueLimitExceeded,
+                            String.valueOf(ScarabConstants.ISSUE_MAX_VIEW)
+                        );
+                        scarabR.setAlertMessage(msg);
                         return;
                     }
                 }
-                else if (next.indexOf("copy") > -1)
+                else
+                {
+                    scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                    return;
+                }
+            }
+            else if (next.indexOf("copy") > -1)
+            {
+                if (user.hasPermission(ScarabSecurity.ISSUE__ENTER, modules))
                 {
-                    if (user.hasPermission(ScarabSecurity.ISSUE__ENTER, modules))
+                    if (issueIds.size() <= ScarabConstants.ISSUE_MAX_COPY)
                     {
-                        if (issueIds.size() <= ScarabConstants.ISSUE_MAX_COPY)
-                        {
-                            data.getParameters().add("mv_0rb", "copy");
-                            setTarget(data, "MoveIssue.vm");
-                        }
-                        else
-                        {
-                            L10NMessage msg = new L10NMessage
-                            (
-                                L10NKeySet.IssueLimitExceeded,
-                                String.valueOf(ScarabConstants.ISSUE_MAX_COPY)
-                            );
-                            scarabR.setAlertMessage(msg);
-                            return;
-                        }
+                        data.getParameters().add("mv_0rb", "copy");
+                        setTarget(data, "MoveIssue.vm");
                     }
                     else
                     {
-                        scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                        L10NMessage msg = new L10NMessage
+                        (
+                            L10NKeySet.IssueLimitExceeded,
+                            String.valueOf(ScarabConstants.ISSUE_MAX_COPY)
+                        );
+                        scarabR.setAlertMessage(msg);
+                        return;
                     }
                 }
-                else if (next.indexOf("move") > -1)
+                else
+                {
+                    scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                }
+            }
+            else if (next.indexOf("move") > -1)
+            {
+                if (user.hasPermission(ScarabSecurity.ISSUE__MOVE, modules))
                 {
-                    if (user.hasPermission(ScarabSecurity.ISSUE__MOVE, modules))
+                    if (issueIds.size() <= ScarabConstants.ISSUE_MAX_MOVE)
                     {
-                        if (issueIds.size() <= ScarabConstants.ISSUE_MAX_MOVE)
-                        {
-                            data.getParameters().add("mv_0rb", "move");
-                            setTarget(data, "MoveIssue.vm");
-                        }
-                        else
-                        {
-                            L10NMessage msg = new L10NMessage
-                            (
-                                L10NKeySet.IssueLimitExceeded,
-                                String.valueOf(ScarabConstants.ISSUE_MAX_MOVE)
-                            );
-                            scarabR.setAlertMessage(msg);
-                            return;
-                        }
+                        data.getParameters().add("mv_0rb", "move");
+                        setTarget(data, "MoveIssue.vm");
                     }
                     else
                     {
-                        scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                        L10NMessage msg = new L10NMessage
+                        (
+                            L10NKeySet.IssueLimitExceeded,
+                            String.valueOf(ScarabConstants.ISSUE_MAX_MOVE)
+                        );
+                        scarabR.setAlertMessage(msg);
+                        return;
                     }
                 }
+                else
+                {
+                    scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
+                }
             }
-            else
-            {
-                String template = data.getParameters()
-                    .getString(ScarabConstants.NEXT_TEMPLATE,
-                               getIssueListTarget());
-                setTarget(data, template);
-            }
+        }
+        else
+        {
+            String template = data.getParameters()
+                .getString(ScarabConstants.NEXT_TEMPLATE,
+                           getIssueListTarget());
+            setTarget(data, template);
         }
     }
 
@@ -286,7 +281,7 @@
     {
         setup(data, context);
         String queryString = getQueryString(data);        
-        user.setMostRecentQuery(queryString);
+        setRecentQuery(queryString);
 
         doPerform(data, context);
     }
@@ -300,7 +295,7 @@
         setup(data, context);
         if (data.getParameters().getString("refine") != null)
         {
-            user.setMostRecentQuery(getQueryString(data));
+            setRecentQuery(getQueryString(data));
         }
 
         if (scarabR.hasPermission(ScarabSecurity.USER__EDIT_PREFERENCES))
@@ -514,7 +509,7 @@
            losing users and maybe the mitlist, so revisit this later.
         user.setMostRecentQuery(query.getValue());
         */
-        user.setMostRecentQuery(getQueryString(data));
+        setRecentQuery(getQueryString(data));
         scarabR.resetSelectedUsers();
     }
 
@@ -532,7 +527,7 @@
         query.saveAndSendEmail((ScarabUser)data.getUser(), 
                  scarabR.getCurrentModule(), context);
         scarabR.resetSelectedUsers();
-        user.setMostRecentQuery(newValue);
+        setRecentQuery(newValue);
     }
 
     /**
@@ -550,7 +545,7 @@
         {
             mitList.setScarabUser(user);
         }
-        user.setMostRecentQuery(query.getValue());
+        setRecentQuery(query.getValue());
         
         //
         // Add 'sortColumn', 'sortPolarity' and 'resultsPerPage'
@@ -630,7 +625,7 @@
                 String query = sb.append("&user_list=").append(userId)
                     .append("&user_attr_").append(userId).append("=any")
                     .toString();
-                user.setMostRecentQuery(query);
+                setRecentQuery(query);
                 setTarget(data, getIssueListTarget());
             }
             else if (go.equals("myIssuesAllModules"))
@@ -642,7 +637,7 @@
                 String query = sb.append("&user_list=").append(userId)
                     .append("&user_attr_").append(userId).append("=any")
                     .toString();
-                user.setMostRecentQuery(query);
+                setRecentQuery(query);
                 setTarget(data, getIssueListTarget());
             }
             else if (go.equals("quickSearch"))
@@ -677,7 +672,7 @@
                             }
                         }
                     }
-                    quickSearch(searchString, attributeMap, user, context);
+                    quickSearch(searchString, attributeMap, user);
                 }
                 setTarget(data, getIssueListTarget());
             }
@@ -690,23 +685,6 @@
             {
                 setTarget(data, go);
             }
-            if (go.equals("myIssues") || go.equals("mostRecent"))
-            {
-                IteratorWithSize searchResults = null;
-                try
-                {
-                    searchResults = scarabR.getCurrentSearchResults();
-                }
-                catch (java.lang.IllegalArgumentException e)
-                {
-                    // Swallow this exception.
-                    Log.get().debug("", e);
-                }
-                if (searchResults != null && searchResults.size() > 0)
-                {
-                    context.put("issueList", searchResults);
-                }
-            }
         }
         else
         {
@@ -719,11 +697,17 @@
         }
     }
 
+    private void setRecentQuery(String query)
+    {
+        user.setMostRecentQuery(query);
+        scarabR.clearCachedQueryResult();
+    }
+
     /**
      * @param attributeMap
      * @return
      */
-    private void quickSearch(String searchString, Map attributeMap, ScarabUser user, TemplateContext context)
+    private void quickSearch(String searchString, Map attributeMap, ScarabUser user)
     {
         String queryPart;
 
@@ -734,11 +718,12 @@
             Integer id = (Integer)iter.next();
             queryPart += "&attv__"+id+"val="+searchString;
         }
+        queryPart += "&searchmptq=true";
         
-        processSearch(queryPart, user, context);
+        processSearch(queryPart, user);
     }
 
-    private void processSearch(String queryPart, ScarabUser user, TemplateContext context)
+    private void processSearch(String queryPart, ScarabUser user)
     {
         String query;
 
@@ -758,29 +743,16 @@
         query += queryPart;
         query += queryEnd;
 
-        user.setMostRecentQuery(query.toLowerCase());
-        
-        IteratorWithSize searchResults = null;
-        try
-        {
-            searchResults = scarabR.getCurrentSearchResults();
-        }
-        catch (java.lang.IllegalArgumentException e)
-        {
-            // Swallow this exception.
-            Log.get().debug("", e);
-        }
-        if (searchResults != null && searchResults.size() > 0)
-        {
-            context.put("issueList", searchResults);
-        }
+        setRecentQuery(query);
+
     }
+
     
-    private void attributeSearch(String optionValue, AttributeValue attributeValue, ScarabUser user, TemplateContext context)
+    private void attributeSearch(String optionValue, AttributeValue attributeValue, ScarabUser user)
     {
         Integer id = (attributeValue.getAttributeId());
         String queryPart = "&attv__"+id+"val="+optionValue;
-        processSearch(queryPart, user, context);
+        processSearch(queryPart, user);
     }
     
     
@@ -791,7 +763,7 @@
          throws Exception
     {        
         context.put("refine", "true");
-        setTarget(data, "AdvancedQuery.vm");            
+        setTarget(data, "AdvancedQuery.vm");    
     }
 
 
@@ -963,12 +935,12 @@
 
             AttributeValue av = AttributeValue.getNewInstance(attribute, null);
             String aoname = ao.getName();
-            attributeSearch(aoname, av, user, context);
+            attributeSearch(aoname, av, user);
         }
         else
         {
             // search all issues in current MITList (see MITList initializatoin above)
-            processSearch("",  user, context);
+            processSearch("",  user);
         }
 
         return;
@@ -1009,12 +981,11 @@
         }
         data.getParameters().setString(ScarabConstants.CANCEL_TEMPLATE,
                                        getCurrentTemplate(data));
-        user.setMostRecentQuery(getQueryString(data));
+        setRecentQuery(getQueryString(data));
         IssueSearch search = scarabR.getPopulatedSearch();
         if (search != null)
         {
             setTarget(data, "UserList.vm");
-            IssueSearchFactory.INSTANCE.notifyDone();       
         }
     } 
 
@@ -1074,76 +1045,41 @@
             loadUsersFromUserList(data, userMap);
         }
 
-       ScarabUser newUser = scarabR.getUserByUserName(userName);        
-       boolean success = false;
-       // we are only interested in users that can be assignees
-       if (newUser != null)
-       {
-           MITList mitList = user.getCurrentMITList();
-           List modules = mitList.getModules();
-           if (ANY.equals(attrId))
-           {
-               success = false;
-               // check that the user has at least one applicable attribute
-               for (Iterator i = mitList.getCommonUserAttributes().iterator(); 
-                    i.hasNext() && !success;) 
-               {
-                   success = newUser.hasPermission(
-                       ((Attribute)i.next()).getPermission(), modules);
-               }
-               if (!success) 
-               {
-                   // check created by
-                   success = newUser.hasPermission(ScarabSecurity.ISSUE__ENTER,
-                                                   modules);
-               }
-           }
-           else if (CREATED_BY.equals(attrId))
-           {
-               success = newUser.hasPermission(ScarabSecurity.ISSUE__ENTER, 
-                                               modules);
-           }
-           else
-           {
-               try
-               {
-                   Attribute attribute = 
-                       scarabR.getAttribute(new Integer(attrId));
-                   success = newUser.hasPermission(attribute.getPermission(), 
-                                                   modules);
-               }
-               catch (Exception e)
-               {
-                   // don't allow adding the user
-                   success = false;
-                   Log.get().error("Error trying to get user ," + userName + 
-                       ", for a query. Attribute id = " + attrId, e);
-               }
-           }
-       }
-
-       if (success)
-       {
-           String userId = newUser.getUserId().toString();
-           addAttributeToMap(userMap, userId, attrId, context);
-           user.setSelectedUsersMap(userMap);
-           scarabR.setConfirmMessage(L10NKeySet.SelectedUsersWereAdded);
-       }
-       else
-       {
-           scarabR.setAlertMessage(L10NKeySet.UserNotPossibleAssignee);
-       }
+        String userId = null;
+       
+        if(IssueSearch.SEARCHING_USER_KEY.equalsIgnoreCase(userName))
+        {
+            userId=userName;
+        }
+        else
+        {
+            ScarabUser newUser = scarabR.getUserByUserName(userName);        
+            if (newUser != null)
+            {
+                userId = newUser.getUserId().toString();
+            }
+        }
+    
+        if (userId!=null)
+        {
+            addAttributeToMap(userMap, userId, attrId, context);
+            user.setSelectedUsersMap(userMap);
+            scarabR.setConfirmMessage(L10NKeySet.SelectedUsersWereAdded);
+        }
+        else
+        {
+            scarabR.setAlertMessage(L10NKeySet.UserNotPossibleAssignee);
+        }
     }
 
     private void addAttributeToMap(Map userMap, String userId, String attrId, 
                                    TemplateContext context)
     {
         ScarabRequestTool scarabR = getScarabRequestTool(context);
-        ScarabLocalizationTool l10n = getLocalizationTool(context);
-        List attrIds = (List)userMap.get(userId);
+        Set attrIds = (Set)userMap.get(userId);
         if (attrIds == null) 
         {
-            attrIds = new ArrayList(3);
+            attrIds = new HashSet();
             userMap.put(userId, attrIds);
         }
 
@@ -1196,7 +1132,7 @@
                 String userAttrId = userAttrIds[i];
                 int delimPos = userAttrId.indexOf('_');
                 String userId = userAttrId.substring(0, delimPos);
-                List currentAttrIds = (List)userMap.get(userId);
+                Set currentAttrIds = (Set)userMap.get(userId);
                 if (currentAttrIds.size() == 1) 
                 {
                     userMap.remove(userId);                    

Modified: trunk/src/java/org/tigris/scarab/actions/base/RequireLoginFirstAction.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/actions/base/RequireLoginFirstAction.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/actions/base/RequireLoginFirstAction.java&p2=trunk/src/java/org/tigris/scarab/actions/base/RequireLoginFirstAction.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/actions/base/RequireLoginFirstAction.java	(original)
+++ trunk/src/java/org/tigris/scarab/actions/base/RequireLoginFirstAction.java	2007-06-09 08:06:34-0700
@@ -64,6 +64,7 @@
 import org.tigris.scarab.services.security.ScarabSecurity;
 import org.tigris.scarab.tools.ScarabLocalizationTool;
 import org.tigris.scarab.tools.ScarabRequestTool;
+import org.tigris.scarab.tools.ScarabGlobalTool;
 import org.tigris.scarab.tools.localization.L10NKeySet;
 import org.tigris.scarab.tools.localization.LocalizationKey;
 import org.tigris.scarab.util.ScarabConstants;
@@ -168,6 +169,15 @@
     }
 
     /**
+     * Helper method to retrieve the ScarabGlobalTool from the Context
+     */
+    public ScarabGlobalTool getScarabGlobalTool(TemplateContext context)
+    {
+        return (ScarabGlobalTool)context
+            .get(ScarabConstants.SCARAB_GLOBAL_TOOL);
+    }
+
+    /**
      * Returns the current template that is being executed, otherwisse
      * it returns null
      */

Modified: trunk/src/java/org/tigris/scarab/attribute/DateAttribute.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/attribute/DateAttribute.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/attribute/DateAttribute.java&p2=trunk/src/java/org/tigris/scarab/attribute/DateAttribute.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/attribute/DateAttribute.java	(original)
+++ trunk/src/java/org/tigris/scarab/attribute/DateAttribute.java	2007-06-09 08:06:34-0700
@@ -3,9 +3,9 @@
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
+import java.util.Date;
 import java.util.Iterator;
 
-import org.apache.torque.TorqueException;
 import org.tigris.scarab.om.AttributeValue;
 
 /* ================================================================
@@ -99,7 +99,7 @@
     public static String internalDateFormat(String value, String mask)
     {
         SimpleDateFormat sdf = new SimpleDateFormat(mask);
-        String val = value;
+        String val = null;
         try
         {
             if (val == null)
@@ -109,19 +109,29 @@
         }
         catch (ParseException e)
         {
-            // Will return the same value
+        	val = value;
         }
         return val;
     }
-    
+ 
+    /**
+     * returns a date as string
+     * formatted in internal (yyyyMMddHHmmssSS) format.
+     * @param date
+     * @return date string
+     */
+    public static String internalDateFormat(Date date)
+    {
+      	return internalFormat.format(date);
+    }
+
     /**
      * Utility method that will convert every DateAttribute in a list from the user's
      * locale format to the internal (yyyyMMddHHmmssSS) format.
      * @param issue
      * @param mask
-     * @throws TorqueException
      */
-    public static void convertDateAttributes(Collection attributeValues, String mask) throws TorqueException
+    public static void convertDateAttributes(Collection attributeValues, String mask)
     {
         for (Iterator iter = attributeValues.iterator(); iter.hasNext(); )
         {

Modified: trunk/src/java/org/tigris/scarab/feeds/QueryFeed.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/feeds/QueryFeed.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/feeds/QueryFeed.java&p2=trunk/src/java/org/tigris/scarab/feeds/QueryFeed.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/feeds/QueryFeed.java	(original)
+++ trunk/src/java/org/tigris/scarab/feeds/QueryFeed.java	2007-06-09 08:06:34-0700
@@ -12,7 +12,6 @@
 import org.tigris.scarab.om.IssueManager;
 import org.tigris.scarab.om.Query;
 import org.tigris.scarab.om.RModuleUserAttribute;
-import org.tigris.scarab.util.IteratorWithSize;
 import org.tigris.scarab.util.ScarabLink;
 import org.tigris.scarab.util.ScarabUtil;
 import org.tigris.scarab.util.word.QueryResult;
@@ -35,7 +34,7 @@
 public class QueryFeed implements Feed {
 
     private Query query;
-    private IteratorWithSize results;
+    private List results;
     private ScarabLink scarabLink;
     private String format;
     
@@ -48,7 +47,7 @@
      * @param scarabLink
      * @param format 
      */
-    public QueryFeed(Query query, IteratorWithSize results, ScarabLink scarabLink, String format) {
+    public QueryFeed(Query query, List results, ScarabLink scarabLink, String format) {
         this.query = query;
         this.results = results;
         this.scarabLink = scarabLink;
@@ -57,27 +56,18 @@
 
     public SyndFeed getFeed() throws Exception, TorqueException, DataSetException, TurbineSecurityException
     {
-        boolean showModuleName = !query.getMITList().isSingleModule();
-        boolean showIssueType = !query.getMITList().isSingleIssueType();
-
         SyndFeed feed = new SyndFeedImpl();
         feed.setTitle(query.getName());
         String link = scarabLink.setAction("Search").addPathInfo("go",query.getQueryId()).toString();
         feed.setLink(link);
         feed.setDescription(query.getDescription());
         List entries = new ArrayList();
-        while (results.hasNext())
+        for(Iterator i = results.iterator(); i.hasNext();)
         {
             SyndEntry entry = new SyndEntryImpl();
             SyndContent description = new SyndContentImpl();
-            QueryResult queryResult = (QueryResult)results.next();
+            QueryResult queryResult = (QueryResult)i.next();
             String title = queryResult.getUniqueId();
-            if(showModuleName){
-                title = title + " ("+ queryResult.getModule().getRealName() + ")";
-            }
-            if(showIssueType){
-                title = title + " ("+ queryResult.getRModuleIssueType().getDisplayName() + ")";
-            }
             entry.setTitle(title);
             
             Issue issue = IssueManager.getInstance(Long.valueOf(queryResult.getIssueId()));
@@ -115,4 +105,4 @@
         return feed;
     }    
     
-}
\ No newline at end of file
+}

Modified: trunk/src/java/org/tigris/scarab/om/Attribute.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Attribute.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/om/Attribute.java&p2=trunk/src/java/org/tigris/scarab/om/Attribute.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/Attribute.java	(original)
+++ trunk/src/java/org/tigris/scarab/om/Attribute.java	2007-06-09 08:06:34-0700
@@ -151,7 +151,17 @@
     public static Attribute getInstance(int id)
         throws TorqueException
     {
-        return AttributeManager.getInstance(new Integer(id));
+        return getInstance(new Integer(id));
+    }
+
+    /**
+     * Return an instance based on the passed in attribute id as an int
+     * It will return a cached instance if possible.
+     */
+    public static Attribute getInstance(Integer id)
+        throws TorqueException
+    {
+        return AttributeManager.getInstance(id);
     }
 
 

Modified: trunk/src/java/org/tigris/scarab/om/AttributeValue.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/AttributeValue.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/om/AttributeValue.java&p2=trunk/src/java/org/tigris/scarab/om/AttributeValue.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/AttributeValue.java	(original)
+++ trunk/src/java/org/tigris/scarab/om/AttributeValue.java	2007-06-09 08:06:34-0700
@@ -94,8 +94,6 @@
     private String activityDescription = null;
     private Activity saveActivity = null;
 
-    private static String className = "AttributeValue";
-
     
     /** Creates a new attribute. Do not do anything here.
      * All initialization should be performed in init().
@@ -424,22 +422,9 @@
                 // FIXME! create a key and get the instance directly from
                 // the manager.
                 List options = null;
-                try
-                {
-                    options = module
+
+                options = module
                         .getRModuleOptions(getAttribute(), issueType);
-                }
-                catch (Exception e)
-                {
-                    if (e instanceof TorqueException) 
-                    {
-                        throw (TorqueException)e; //EXCEPTION
-                    }
-                    else 
-                    {
-                        throw new TorqueException(e); //EXCEPTION
-                    }
-                }
                 if(options != null)
                 {
                     for (int i = options.size() - 1; i >= 0; i--)
@@ -546,7 +531,6 @@
      * @exception Exception if an error occurs
      */
     public Integer[] getOptionIds()
-        throws TorqueException
     {
         List optionIds = new ArrayList();
         if (getOptionId() != null) 
@@ -596,7 +580,7 @@
      * @exception Exception if an error occurs
      */
     public Integer[] getUserIds()
-        throws TorqueException, ScarabException
+        throws ScarabException
     {
         throw new ScarabException(L10NKeySet.ExceptionGetUserIdsNotImplemented);
     }
@@ -678,6 +662,28 @@
         }
         return rma;
     }
+    
+	public String getDisplayValue()
+	    throws TorqueException
+	{
+		String displayValue = null;
+		
+		if(getAttribute().isOptionAttribute())
+	    {
+			displayValue = getIssue().getModule().getRModuleOption( getAttributeOption(), getIssue().getIssueType()).getDisplayValue();
+			//displayValue = getRModuleAttribute().getDisplayValue();
+	    }
+		else if(getAttribute().isUserAttribute())
+		{
+			displayValue = getScarabUser().getUserName();
+		}
+	    else
+	    {
+	    	displayValue = getValue();
+	    }
+		return displayValue;
+	}
+
 
     public AttributeOption getAttributeOption()
         throws TorqueException
@@ -806,18 +812,14 @@
     {
         if (isModified() && !getAttribute().isUserAttribute())
         {
-            String desc = null;
             try
             {
                 checkActivitySet(L10NKeySet.ExceptionCanNotSaveAttributeValue);
-                desc = getActivityDescription();
             }
             catch (Exception e)
             {
-                throw new TorqueException(e); //EXCEPTION
+                throw new TorqueException(e);
             }
-            // Save activity record
-            // Save new activity record, if activity has not been set
             if (saveActivity == null)
             {            
                 if (getDeleted())
@@ -961,6 +963,3 @@
         return ScarabConstants.DEFAULT_LOCALE;
     }
 }
-
-
-

Modified: trunk/src/java/org/tigris/scarab/om/Issue.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/Issue.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/om/Issue.java&p2=trunk/src/java/org/tigris/scarab/om/Issue.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/Issue.java	(original)
+++ trunk/src/java/org/tigris/scarab/om/Issue.java	2007-06-09 08:06:34-0700
@@ -48,8 +48,6 @@
 
 // JDK classes
 import com.workingdogs.village.DataSetException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.io.Serializable;
 import java.sql.Connection;
 import java.util.ArrayList;
@@ -90,7 +88,6 @@
 import org.tigris.scarab.util.MutableBoolean;
 import org.tigris.scarab.util.ScarabConstants;
 import org.tigris.scarab.util.ScarabException;
-import org.tigris.scarab.util.ScarabRuntimeException;
 import org.tigris.scarab.workflow.WorkflowFactory;
 
 import com.workingdogs.village.Record;
@@ -182,7 +179,7 @@
      * new issues are created only when the issuetype and module are known
      * Or by the Peer when retrieving from db
      */
-    protected Issue()
+    public Issue()
     {
     }
 
@@ -946,19 +943,28 @@
     }
 
     /**
+     * Returns the (undeleted) AttributeValues for the attributeId.
+     */
+    public List getAttributeValues(Integer id)
+       throws TorqueException
+    {
+        Attribute attribute = Attribute.getInstance(id);
+        return getAttributeValues(attribute);
+    }
+    
+    /**
      * Returns the (undeleted) AttributeValues for the Attribute.
      */
     public List getAttributeValues(final Attribute attribute)
        throws TorqueException
     {
-        List result = null;
-        Object obj = ScarabCache.get(this, GET_ATTRVALUES, attribute); 
-        if (obj == null) 
+        List aval = (List)IssueManager.getMethodResult().get(this, GET_ATTRVALUES, attribute); 
+        if (aval == null) 
         {        
             if (isNew()) 
             {
                 final List avals = getAttributeValues();
-                result = new ArrayList();
+                aval = new ArrayList();
                 if (avals != null) 
                 {
                     final Iterator i = avals.iterator();
@@ -967,7 +973,7 @@
                         final AttributeValue tempAval = (AttributeValue)i.next();
                         if (tempAval.getAttribute().equals(attribute)) 
                         {
-                            result.add(tempAval);
+                            aval.add(tempAval);
                         }
                     }
                 }
@@ -979,15 +985,11 @@
                     .add(AttributeValuePeer.ATTRIBUTE_ID, 
                          attribute.getAttributeId());
                 
-                result = getAttributeValues(crit);
-                ScarabCache.put(result, this, GET_ATTRVALUES, attribute);
+                aval = getAttributeValues(crit);
+                IssueManager.getMethodResult().put(aval, this, GET_ATTRVALUES, attribute);
             }
         }
-        else 
-        {
-            result = (List)obj;
-    }
-        return result;
+        return aval;
     }
 
     public boolean isAttributeValue(AttributeValue attVal)

Modified: trunk/src/java/org/tigris/scarab/om/RModuleUserAttribute.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/om/RModuleUserAttribute.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/om/RModuleUserAttribute.java&p2=trunk/src/java/org/tigris/scarab/om/RModuleUserAttribute.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/om/RModuleUserAttribute.java	(original)
+++ trunk/src/java/org/tigris/scarab/om/RModuleUserAttribute.java	2007-06-09 08:06:34-0700
@@ -133,6 +133,8 @@
     public static Attribute MODIFIED_DATE = new Attribute();
     public static Attribute CREATED_BY = new Attribute();
     public static Attribute CREATED_DATE = new Attribute();
+    public static Attribute MODULE = new Attribute();
+    public static Attribute ISSUE_TYPE = new Attribute();
     
     public static Set internalAttributes = new HashSet();
     static
@@ -141,10 +143,14 @@
         MODIFIED_DATE.setName(L10NKeySet.ModifiedDate.toString());
         CREATED_BY.setName(L10NKeySet.CreatedBy.toString());
         CREATED_DATE.setName(L10NKeySet.CreatedDate.toString());
+        MODULE.setName(L10NKeySet.Module.toString());
+        ISSUE_TYPE.setName( L10NKeySet.IssueType.toString());
         internalAttributes.add(MODIFIED_BY);
         internalAttributes.add(MODIFIED_DATE);
         internalAttributes.add(CREATED_BY);
         internalAttributes.add(CREATED_DATE);
+        internalAttributes.add(MODULE);
+        internalAttributes.add(ISSUE_TYPE);
     }
 
     public boolean isInternal()

Modified: trunk/src/java/org/tigris/scarab/reports/ReportBridge.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/reports/ReportBridge.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/reports/ReportBridge.java&p2=trunk/src/java/org/tigris/scarab/reports/ReportBridge.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/reports/ReportBridge.java	(original)
+++ trunk/src/java/org/tigris/scarab/reports/ReportBridge.java	2007-06-09 08:06:34-0700
@@ -691,20 +691,24 @@
             {
                 ReportOptionAttribute roa = (ReportOptionAttribute)i.next();
                 Integer optionId = roa.getOptionId();
-                Integer attId = AttributeOptionManager.getInstance(optionId)
-                    .getAttributeId();
-                AttributeValue av = AttributeValue
-                    .getNewInstance(attId, search);
-                av.setOptionId(optionId);
+                AttributeOption ao = 
+                    AttributeOptionManager.getInstance(optionId);
+
+                Integer attId = AttributeOptionManager.getInstance(optionId).getAttributeId();
+                Attribute attr = AttributeManager.getInstance(attId); 
                 if (commonAttributeMap.containsKey(attId)) 
                 {
+                    //FIXME is null as Issue really ok?
+                	AttributeValue av = AttributeValue
+                    .getNewInstance(attr, null);
+                    av.setAttributeOption(ao);
                     AttributeValue prevAV = 
                         (AttributeValue)commonAttributeMap.get(attId);
                     prevAV.setChainedValue(av);
                 }
                 else 
                 {
-                    search.addAttributeValue(av);
+                	AttributeValue av = search.addAttributeValue(attr, ao);
                     commonAttributeMap.put(attId, av);
                 }
             }

Modified: trunk/src/java/org/tigris/scarab/screens/IssueList.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/screens/IssueList.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/screens/IssueList.java&p2=trunk/src/java/org/tigris/scarab/screens/IssueList.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/screens/IssueList.java	(original)
+++ trunk/src/java/org/tigris/scarab/screens/IssueList.java	2007-06-09 08:06:34-0700
@@ -46,6 +46,8 @@
  * individuals on behalf of Collab.Net.
  */ 
 
+import java.util.List;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.turbine.RunData;
 import org.apache.turbine.TemplateContext;
@@ -61,6 +63,40 @@
  * @author <a href="mailto:[email protected]">Peter Ledbrook</a>
  */
 public class IssueList extends Default {
+
+    protected void doBuildTemplate(RunData data, TemplateContext context)
+    throws Exception
+    {
+        super.doBuildTemplate(data, context);
+        populateContextWithQueryResults(data, context);
+        
+    }
+
+    private void populateContextWithQueryResults(RunData data, TemplateContext context)
+    {
+        ScarabRequestTool scarabR = getScarabRequestTool(context);
+        
+        List searchResults = scarabR.getCurrentSearchResults();
+        int searchResultsSize = searchResults.size();
+        int resultsPerPage = data.getParameters().getInt("resultsPerPage", 25);
+        int pageNum = data.getParameters().getInt("pageNum", 1 );
+        boolean paginated = resultsPerPage > 0 && searchResultsSize > resultsPerPage;
+        
+        if(paginated)
+        {
+            searchResults = scarabR.getPaginatedList(searchResults, pageNum, resultsPerPage);
+            
+        }
+        int isueListSize = searchResults.size();
+        
+        context.put("queryResults", searchResults );
+        context.put("pageNum", new Integer(pageNum));
+        context.put("totalCount", new Integer(searchResultsSize));
+        context.put("isueListSize", new Integer(isueListSize));
+        context.put("paginated", new Boolean(paginated));
+        context.put("resultsPerPage", new Integer(resultsPerPage));        
+    }
+    
     /**
      * Returns a localised title for the issue list screen,
      * which includes the source query name if there is one.

Modified: trunk/src/java/org/tigris/scarab/screens/IssueListExport.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/screens/IssueListExport.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/screens/IssueListExport.java&p2=trunk/src/java/org/tigris/scarab/screens/IssueListExport.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/screens/IssueListExport.java	(original)
+++ trunk/src/java/org/tigris/scarab/screens/IssueListExport.java	2007-06-09 08:06:34-0700
@@ -114,18 +114,6 @@
                               ScarabLocalizationTool l10n, List rmuas)
         throws Exception
     {
-        if (mitlist != null)
-        {
-            if (!mitlist.isSingleModule())
-            {
-                printer.print((new L10NMessage(L10NKeySet.CapModule).getMessage(l10n)));
-            }
-
-            if (!mitlist.isSingleIssueType())
-            {
-                printer.print((new L10NMessage(L10NKeySet.IssueType).getMessage(l10n)));
-            }
-        }
 
         printer.print((new L10NMessage(L10NKeySet.IssueId).getMessage(l10n)));
 
@@ -170,7 +158,7 @@
             ScarabLocalizationTool l10n, ScarabRequestTool scarabR, List rmuas)
         throws Exception
     {
-        for (Iterator i = scarabR.getCurrentSearchResults();i.hasNext();)
+        for (Iterator i = scarabR.getCurrentSearchResults().iterator();i.hasNext();)
         {
             printer.println();
             QueryResult queryResult = (QueryResult)i.next();
@@ -195,18 +183,6 @@
     private void writeRow(TSVPrinter printer, MITList mitlist, QueryResult queryResult)
         throws Exception
     {
-        if (mitlist != null)
-        {
-            if (!mitlist.isSingleModule())
-            {
-                printer.print(queryResult.getModule().getRealName());
-            }
-
-            if (!mitlist.isSingleIssueType())
-            {
-                printer.print(queryResult.getRModuleIssueType().getDisplayName());
-            }
-        }
 
         printer.print(queryResult.getUniqueId());
 

Modified: trunk/src/java/org/tigris/scarab/screens/admin/ViewXMLExportIssues.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/screens/admin/ViewXMLExportIssues.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/screens/admin/ViewXMLExportIssues.java&p2=trunk/src/java/org/tigris/scarab/screens/admin/ViewXMLExportIssues.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/screens/admin/ViewXMLExportIssues.java	(original)
+++ trunk/src/java/org/tigris/scarab/screens/admin/ViewXMLExportIssues.java	2007-06-09 08:06:34-0700
@@ -111,12 +111,12 @@
             final StringBuffer sb = new StringBuffer();
             final Search searchAction = new Search();
             searchAction.doSelectquery(data, context);
-            final Iterator it = scarabR.getCurrentSearchResults();
+            final Iterator it = scarabR.getCurrentSearchResults().iterator();
             while(it.hasNext())
             {
                 final QueryResult issue = (QueryResult)it.next();
-                sb.append(issue.getIdPrefix()+issue.getIdCount());
-                allIdList.add(issue.getIdPrefix()+issue.getIdCount());
+                sb.append(issue.getUniqueId());
+                allIdList.add(issue.getUniqueId());
                 if(it.hasNext())
                 {
                     sb.append(',');

Added: trunk/src/java/org/tigris/scarab/search/CachedQuery.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/search/CachedQuery.java?view=auto&rev=10445
==============================================================================
--- (empty file)
+++ trunk/src/java/org/tigris/scarab/search/CachedQuery.java	2007-06-09 08:06:34-0700
@@ -0,0 +1,153 @@
+package org.tigris.scarab.search;

+

+import java.util.ArrayList;

+import java.util.List;

+import org.tigris.scarab.util.Log;

+

+import com.workingdogs.village.Record;

+

+import org.apache.torque.util.Criteria;

+import org.apache.torque.util.BasePeer;

+import org.apache.torque.TorqueException;

+

+public class CachedQuery {

+    private static final char DOT_REPLACEMENT_IN_JOIN_CONDITION = '#';

+	private static final int MAXIMUM_INITIAL_ROWS = 1000;

+	private static final String LOGGER = "org.apache.torque";

+

+    private Criteria criteria;

+    private boolean countOnly = false;

+    private List cachedRows;

+    private int totalRowCount;

+    private CachedResultList results;

+    

+	public CachedQuery( Criteria criteria, boolean countOnly )

+	{

+		this.criteria  = criteria;

+		this.countOnly = countOnly;

+	}

+

+    private static List executeSelect( String sql )

+        throws TorqueException

+    {

+		List result;

+		try 

+    	{

+	        long queryStartTime = System.currentTimeMillis();

+

+		    result = BasePeer.executeQuery(sql);

+	        

+	        logLongRunningQuery(sql, System.currentTimeMillis() - queryStartTime);

+        }

+	    catch (TorqueException e)

+        {

+            Log.get(LOGGER).warn("Search sql:\n" + sql + 

+                "\nresulted in an exception: " + e.getMessage());

+            throw e;

+        }

+        return result;

+    }       		

+

+    public List getResults()

+    {

+        if(countOnly)

+        	throw new RuntimeException("is countOnly!");

+

+        if(results==null)

+    		results = new CachedResultList(this);

+    	

+    	return results;

+    }

+    

+    public int getRowCount()

+    {

+    	cacheInitial();

+    	return totalRowCount();

+    }

+	

+    public void cacheInitial()

+    {

+    	if(cachedRows==null)

+    	{

+    		try

+    		{

+				if(!countOnly)

+	    		{

+	    	        criteria.setLimit(MAXIMUM_INITIAL_ROWS).setOffset(0);

+	    	    	String sql = adjustSelectSql(BasePeer.createQueryString(criteria));

+	    		    cachedRows = executeSelect(sql);

+	    		}	    		

+

+				if(cachedRows==null) cachedRows = new ArrayList();

+	

+	            totalRowCount = cachedRows.size(); 

+    		

+			    if(countOnly || cachedRows.size()==MAXIMUM_INITIAL_ROWS)

+			    {

+	    	        criteria.setLimit(-1).setOffset(0);

+	    	    	String sql = adjustSelectSql(BasePeer.createQueryString(criteria));

+			        sql = makeCountSql(sql);

+	                List countRows = executeSelect(sql);

+	                Record countRow = (Record)countRows.get(0);   

+	                totalRowCount = countRow.getValue(1).asInt();

+			    }

+    		}

+		    catch(Exception e)

+    		{

+    			throw new RuntimeException(e);

+    		}

+    	}

+    }

+

+    public void cacheAll()

+	{

+		if(cachedRows==null)

+			cacheInitial();

+		

+    	if(cachedRowCount() < totalRowCount())

+		{

+    		try

+    		{

+		        criteria.setLimit(-1).setOffset(cachedRowCount());

+		    	String sql = adjustSelectSql(BasePeer.createQueryString(criteria));

+			    cachedRows.addAll(executeSelect(sql));

+		    }

+			catch(Exception e)

+    		{

+    			throw new RuntimeException(e);

+    		}

+	        

+		}

+	}

+

+	public List getCachedRows()

+	{

+		return cachedRows;

+    }

+    

+	public int cachedRowCount()

+	{

+		return cachedRows.size();

+	}

+

+	public int totalRowCount()

+	{

+		return totalRowCount;

+	}

+

+	private static String adjustSelectSql(String sql)

+    {

+        return sql.replace(DOT_REPLACEMENT_IN_JOIN_CONDITION, '.');

+    }

+

+    private static String makeCountSql(String sql)

+    {

+        return "SELECT COUNT(*) FROM ( " + sql + " ) SEARCH_RESULT";

+    }

+

+    private static void logLongRunningQuery(String sql, long time)

+    {

+        if (time > 500) 

+            Log.get(LOGGER).warn("Long running query:\n" + sql + "\nTime = " + time + " ms");

+    }

+}


Added: trunk/src/java/org/tigris/scarab/search/CachedResultList.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/search/CachedResultList.java?view=auto&rev=10445
==============================================================================
--- (empty file)
+++ trunk/src/java/org/tigris/scarab/search/CachedResultList.java	2007-06-09 08:06:34-0700
@@ -0,0 +1,35 @@
+package org.tigris.scarab.search;

+

+import java.util.AbstractList;

+import org.tigris.scarab.search.CachedQuery;

+

+public class CachedResultList extends AbstractList

+{

+	private CachedQuery query;

+	

+	CachedResultList(CachedQuery query)

+	{

+	    this.query = query;

+	    query.cacheInitial();

+	}

+	

+	public int size()

+	{

+	    return query.totalRowCount();

+	}

+	

+	public Object get(int index)

+	{

+	    if(index>query.totalRowCount())

+	    {

+	        throw new IndexOutOfBoundsException();

+	    }

+	    else if(index>query.cachedRowCount())

+	    {

+	        query.cacheAll();

+		    if(index>query.cachedRowCount())

+		    	index = query.cachedRowCount();

+	    }

+	    return query.getCachedRows().get(index);

+	}

+}


Modified: trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java&p2=trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java	(original)
+++ trunk/src/java/org/tigris/scarab/tools/ScarabRequestTool.java	2007-06-09 08:06:34-0700
@@ -62,8 +62,6 @@
 
 import javax.servlet.http.HttpSession;
 
-import org.apache.commons.collections.map.LinkedMap;
-import org.apache.commons.lang.StringUtils;
 import org.apache.fulcrum.intake.Intake;
 import org.apache.fulcrum.intake.model.Field;
 import org.apache.fulcrum.intake.model.Group;
@@ -126,12 +124,10 @@
 import org.tigris.scarab.om.Transition;
 import org.tigris.scarab.om.TransitionPeer;
 import org.tigris.scarab.reports.ReportBridge;
-import org.tigris.scarab.services.cache.ScarabCache;
 import org.tigris.scarab.tools.localization.L10NKeySet;
 import org.tigris.scarab.tools.localization.L10NMessage;
 import org.tigris.scarab.tools.localization.Localizable;
 import org.tigris.scarab.util.AnonymousUserUtil;
-import org.tigris.scarab.util.IteratorWithSize;
 import org.tigris.scarab.util.Log;
 import org.tigris.scarab.util.ScarabConstants;
 import org.tigris.scarab.util.ScarabException;
@@ -139,9 +135,6 @@
 import org.tigris.scarab.util.ScarabPaginatedList;
 import org.tigris.scarab.util.SimpleSkipFiltering;
 import org.tigris.scarab.util.SnippetRenderer;
-import org.tigris.scarab.util.SubsetIteratorWithSize;
-import org.tigris.scarab.util.WindowIterator;
-import org.tigris.scarab.util.word.ComplexQueryException;
 import org.tigris.scarab.util.word.IssueSearch;
 import org.tigris.scarab.util.word.IssueSearchFactory;
 import org.tigris.scarab.util.word.MaxConcurrentSearchException;
@@ -159,6 +152,8 @@
     private static final String TIME_ZONE =
         Turbine.getConfiguration().getString("scarab.timezone", "");
 
+    private static final String POS_IN_LIST = "posInList";
+
     /**
      * The disposed flag.
      */
@@ -236,11 +231,6 @@
      * A ParentChildAttributeOption
      */
     private ParentChildAttributeOption pcao = null;
-
-    /**
-     * IssueSearch object for performing queries
-     */
-    private IssueSearch issueSearch = null;
     
     /**
      * keep track if the columns were reduced to avoid db limits
@@ -261,8 +251,6 @@
     private int nbrPages = 0;
     private int prevPage = 0;
     private int nextPage = 0;
-    private String cachedNextIssueId;
-    private String cachedPrevIssueId;
 
     /* messages usually set in actions */
     private Object confirmMessage;
@@ -311,14 +299,6 @@
         roo = null;
         pcao = null;
         attributeTypes = new HashMap();
-        if (issueSearch != null)
-        {
-            // This must _always_ be called by dispose()
-            Log.get().debug("IssueSearch object is disposed of properly.");
-            issueSearch.close();
-            IssueSearchFactory.INSTANCE.notifyDone();
-            issueSearch = null;
-        }
         issueListColumns = null;
         initialIssueListColumnsSize = 0;
         reportGenerator = null;
@@ -328,8 +308,6 @@
         confirmMessage = null;
         infoMessage = null;
         alertMessage = null;
-        cachedPrevIssueId = null;
-        cachedNextIssueId = null;
     }
 
     /**
@@ -377,14 +355,6 @@
     }
 
     /**
-     * A Query object for use within the Scarab API.
-     */
-    public void setQuery (Query query)
-    {
-        this.query = query;
-    }
-
-    /**
      * Get the intake tool.
      */
     private IntakeTool getIntakeTool()
@@ -534,32 +504,37 @@
      * will resolve to a String object as id.toString() is 
      * called on everything that isn't a Integer.
      */
-    public ScarabUser getUser(Object id)
-     throws Exception
+    public ScarabUser getUser(Object userId)
+        throws TorqueException
     {
-        if (id == null)
+        if (userId == null)
+        {
+            return null;
+        }
+        
+        if(IssueSearch.SEARCHING_USER_KEY.equalsIgnoreCase(userId.toString()))
+        {
+            return IssueSearch.getSearchingUserPlaceholder();
+        }
+
+        Integer pk = null;
+        try
+        {
+            pk = new Integer(userId.toString());
+        }
+        catch( NumberFormatException e)
         {
             return null;
         }
+
         ScarabUser su = null;
         try
         {
-            Integer pk = null;
-            if (id instanceof Integer)
-            {
-                pk = (Integer) id;
-            }
-            else
-            {
-                pk = new Integer(id.toString());
-            }
             su = ScarabUserManager.getInstance(pk);
         }
-        catch (Exception e)
+        catch (TorqueException e)
         {
-            // Logged at debug level, as a null user is interpreted 
-            // as an invalid user id
-            Log.get().debug("User with user id "+ id +" could not be found,", e);
+            return null;
         }
         return su;
     }
@@ -626,20 +601,11 @@
     /**
      * A Attribute object for use within the Scarab API.
      */
-    public Attribute getAttribute(Integer pk)
+    public Attribute getAttribute(Integer attrId)
      throws Exception
     {
-        Attribute attr = null;
-        try
-        {
-           attr = AttributeManager.getInstance(pk);
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-        }
-        this.attribute = attr;
-        return attr;
+        this.attribute = AttributeManager.getInstance(attrId);
+        return this.attribute;
     }
 
     /**
@@ -1655,70 +1621,20 @@
     }
 
     /**
-     * Get a new IssueSearch object. 
-     *
-     * @return a <code>Issue</code> value
-     */
-    public IssueSearch getNewSearch()
-        throws Exception, MaxConcurrentSearchException
-    {
-        if (issueSearch == null) 
-        {
-            ScarabUser user = (ScarabUser)data.getUser();
-            MITList mitList = user.getCurrentMITList();
-            if (mitList == null)
-            {
-                setAlertMessage(L10NKeySet.NoIssueTypeList);
-                Log.get().warn("Attempted to create a new IssueSearch and " +
-                               " issue types had not been selected.");
-            }
-            else 
-            {
-                issueSearch = 
-                    IssueSearchFactory.INSTANCE.getInstance(mitList, user);
-                issueSearch.setLocale(getLocalizationTool().getPrimaryLocale());
-            }
-        }
-        return issueSearch; 
-    }
-
-    /**
      * Get an IssueSearch object based on a query string.
      *
      * @return a <code>Issue</code> value
      */
-    public IssueSearch getPopulatedSearch(String query)
+    private IssueSearch getPopulatedSearch(String query)
         throws Exception
     {
         IssueSearch search = getNewSearch();
-        if (null == search)
-	        return null;
         
-        ScarabLocalizationTool l10n = getLocalizationTool();
+        search.setLocale(getLocalizationTool().getPrimaryLocale());        
         search.setIssueListAttributeColumns(getRModuleUserAttributes());
         search.setLocalizationTool(getLocalizationTool());
-        search.setQuery(query);
 
-        Intake intake = null;
-
-        if (query == null)
-        {
-            setInfoMessage(L10NKeySet.EnterQuery);
-            //IssueSearchFactory.INSTANCE.notifyDone();
-            //return null;
-            search.setIsOperable(false);
-        }
-        else
-        {
-           intake = parseQuery(query);
-           
-           if (!intake.isAllValid())
-           {
-               //IssueSearchFactory.INSTANCE.notifyDone();
-               //return null;
-               search.setIsOperable(false);
-           }
-        }
+        Intake intake = parseQuery(query);
 
         // If they have entered users to search on, add them to the search
         StringValueParser parser = new StringValueParser();
@@ -1735,140 +1651,106 @@
                 {
                     for (int j = 0; j < attrIds.length; j++) 
                     {
-                        search.addUserCriteria(userId, attrIds[j]);
+                        search.addUserSearch(userId, attrIds[j]);
                     }
                 }
             }
         }
 
-        // Set intake properties
-        int dateFormatErrorCount = 0;
-        String queryKey = search.getQueryKey();
-        Group searchGroup = intake.get("SearchIssue", queryKey);
+        Group searchGroup = intake.get("SearchIssue", search.getQueryKey());
+
+        boolean datesValid = true;
+        Field minCreationDate = searchGroup.get("MinCreationDate");
+        if (minCreationDate!= null && minCreationDate.toString().length() > 0)
+        { 
+        	datesValid &= validateDateFormat(search, minCreationDate);
+        }
         
-        Field minDate = searchGroup.get("MinDate");
-        if (minDate != null && minDate.toString().length() > 0)
+        Field maxCreationDate = searchGroup.get("MaxCreationDate");
+        if (maxCreationDate != null && maxCreationDate.toString().length() > 0)
         { 
-           dateFormatErrorCount += checkDate(search, minDate);
+        	datesValid &= validateDateFormat(search, maxCreationDate);
+        }
+
+        Field minChangeDate = searchGroup.get("MinChangeDate");
+        if (minChangeDate != null && minChangeDate.toString().length() > 0)
+        { 
+        	datesValid &= validateDateFormat(search, minChangeDate);
         }
         
-        Field maxDate = searchGroup.get("MaxDate");
-        if (maxDate != null && maxDate.toString().length() > 0)
+        Field maxChangeDate = searchGroup.get("MaxChangeDate");
+        if (maxChangeDate != null && maxChangeDate.toString().length() > 0)
         { 
-            dateFormatErrorCount += checkDate(search, maxDate);
+        	datesValid &= validateDateFormat(search, maxChangeDate);
         }
         
         Field stateChangeFromDate = searchGroup.get("StateChangeFromDate");
         if (stateChangeFromDate != null 
             && stateChangeFromDate.toString().length() > 0)
         { 
-            dateFormatErrorCount += checkDate(search, stateChangeFromDate);
+        	datesValid &= validateDateFormat(search, stateChangeFromDate);
         }
         
         Field stateChangeToDate = searchGroup.get("StateChangeToDate");
         if (stateChangeToDate != null 
             && stateChangeToDate.toString().length() > 0)
         { 
-            dateFormatErrorCount += checkDate(search, stateChangeToDate);
+        	datesValid &= validateDateFormat(search, stateChangeToDate);
         }
         
-        if (dateFormatErrorCount > 0)
+        if (!datesValid)
         {
         	L10NMessage msg = new L10NMessage(L10NKeySet.DateFormatPrompt,L10NKeySet.ShortDateDisplay);
         	setAlertMessage(msg);
-            //IssueSearchFactory.INSTANCE.notifyDone();
-            //return null;
-            search.setIsOperable(false);
-        }
-        
-        if(search.isOperable())
-        {
-            try
-            {
-                searchGroup.setProperties(search);
-            }
-            catch (Exception e)
-            {
-                setAlertMessage(l10n.getMessage(e));
-                //IssueSearchFactory.INSTANCE.notifyDone();
-                //return null;
-                search.setIsOperable(false);
-            }
+            IssueSearchFactory.INSTANCE.notifyDone();
+            return null;
         }
         
-        Integer oldOptionId = search.getStateChangeFromOptionId();
-        if (oldOptionId != null && oldOptionId.intValue() != 0
-             && oldOptionId.equals(search.getStateChangeToOptionId())) 
-        {
-            setAlertMessage(L10NKeySet.StateChangeOldEqualNew);
-            //IssueSearchFactory.INSTANCE.notifyDone();
-            //return null;
-            search.setIsOperable(false);
-        }
+        searchGroup.setProperties(search);
         
         // Set attribute values to search on
-        LinkedMap avMap;
-        if(searchInAllAttributes)
-        {
-            avMap = search.getAllAvailableAttributeValuesMap();           
-        }
-        else
-        {
-            avMap = search.getCommonAttributeValuesMap();           
-        }
+        Map avMap = search.getAttributeValuesMap(!searchInAllAttributes);           
 
-        Iterator i = avMap.mapIterator();
-        while (i.hasNext()) 
+        for(Iterator i = avMap.values().iterator();i.hasNext();) 
         {
-            Object o            = i.next();
+            AttributeValue aval = (AttributeValue)i.next();
 
-            Object av           = avMap.get(o);
-            AttributeValue aval = (AttributeValue)av;
+            Group group = intake.get("AttributeValue", aval.getQueryKey());
 
-            String qk           = aval.getQueryKey();
-
-            Group group         = intake.get("AttributeValue", qk);
-            if (group != null) 
+            if (group!=null) 
             {
                 group.setProperties(aval);
-            }                
-        }
-        
-        // If user is sorting on an attribute, set sort criteria
-        // Do not use intake, since intake parsed from query is not the same
-        // As intake passed from the form
-        String sortColumn = data.getParameters().getString("sortColumn");
-        String sortInternal=data.getParameters().getString("sortInternal");
-        if (sortColumn != null && sortColumn.length() > 0 
-            && StringUtils.isNumeric(sortColumn))
-        {
-            search.setSortAttributeId(new Integer(sortColumn));
-            search.setSortInternalAttribute(null);
-        }
-        else if (sortInternal != null)
-        {
-            search.setSortInternalAttribute(sortInternal);
-            search.setSortAttributeId(null);
-        } else
-        {
-            // Empty the default sort attribute from the search, so that
-            // the issue ID will apply. 
-            search.setSortAttributeId(null);
-        }    
-        
-        String sortPolarity = data.getParameters().getString("sortPolarity");
-        if (sortPolarity != null && sortPolarity.length() > 0)
-        {
-            search.setSortPolarity(sortPolarity);
+            }
+            
+            if(aval instanceof DateAttribute)
+            {
+                String auxDate = parser.getString("attv__" + aval.getAttributeId().intValue() + "val_aux");
+                
+                if (auxDate != null) 
+                {
+                	AttributeValue auxAval = AttributeValue.getNewInstance(aval.getAttribute(), aval.getIssue());
+                	auxAval.setValue(auxDate);
+                	aval.setChainedValue(auxAval);
+                }
+            }
         }
         
-        // If an error occured, the search ios returned in an inoperable state.
-        // The caller must take care of this, since the search itself does not(!)
-        // obey its own inoperability.
+        search.setSortAttributeId(data.getParameters().getInteger("sortColumn"));
+        search.setSortInternalAttribute(data.getParameters().getString("sortInternal"));
+        search.setSortPolarity(data.getParameters().getString("sortPolarity"));
         
         return search;
     }
 
+    public IssueSearch getNewSearch() throws Exception, MaxConcurrentSearchException
+    {
+        ScarabUser user = (ScarabUser)data.getUser();
+        MITList mitList = user.getCurrentMITList();
+        IssueSearch search = IssueSearchFactory.INSTANCE.getInstance(mitList, user);
+        IssueSearchFactory.INSTANCE.notifyDone();       
+        return search;
+    }
+
     /**
      * Get an IssueSearch object based on current query string.
      *
@@ -1897,111 +1779,86 @@
 
     /**
      * Performs search on current query (which is stored in user session).
-    */
-    public IteratorWithSize getCurrentSearchResults()
+     */
+    public List getCurrentSearchResults()
     {
-        IteratorWithSize matchingIssueIds = null;
+        List queryResults = Collections.EMPTY_LIST;
         try 
         {
-            matchingIssueIds = getUnprotectedCurrentSearchResults();
+            queryResults = getUnprotectedCurrentSearchResults();
+            if (queryResults.size()==0)
+            {
+                setInfoMessage(L10NKeySet.NoMatchingIssues);
+            }
         }
         catch (MaxConcurrentSearchException e)
         {
             setAlertMessage(L10NKeySet.ResourceLimitationsPreventedSearch);
         }
-        catch (ComplexQueryException e)
-        {
-            matchingIssueIds = IteratorWithSize.EMPTY;
-            setAlertMessage(new SimpleSkipFiltering(getLocalizationTool()
-                .format("SearchAbortedDueToComplexity", 
-                        new SnippetRenderer(data, "ComplexQueryHelpLink.vm"))));
-        }
         catch (Exception e)
         {
-            matchingIssueIds = IteratorWithSize.EMPTY;
-            L10NMessage l10nMessage = new L10NMessage(L10NKeySet.ErrorProcessingQuery,e);
-            setAlertMessage(l10nMessage);
-            Log.get().info("Error processing a query", e);
+            String queryError = e.getMessage();
+            if (queryError.startsWith(SearchIndex.PARSE_ERROR)) 
+            {
+                Log.get().info(queryError);
+                setAlertMessage(new SimpleSkipFiltering(
+                        getLocalizationTool().format("QueryParserError", 
+                        new SnippetRenderer(data, "TextQueryHelp.vm"))));
+            }
+            else 
+            {
+                queryResults = Collections.EMPTY_LIST;
+                L10NMessage l10nMessage = new L10NMessage(L10NKeySet.ErrorProcessingQuery,e);
+                setAlertMessage(l10nMessage);
+                Log.get().info("Error processing a query", e);
+            }
         }
         
-        return matchingIssueIds;
+        return queryResults;
     }
 
     /**
-     * Caches the result of getUncachedCurrentSearchResults for the remainder
-     * of the request.
+     * Gets the Result of the current query
+     * and caches it
      */
-    private IteratorWithSize getUnprotectedCurrentSearchResults()
+    private List getUnprotectedCurrentSearchResults()
         throws Exception
     {
-        // normally we would use "this" as the first arg to ScarabCache.get,
-        // but SRT is not serializable.  The result is a mix of a query string
-        // and an MITList and the two should not vary over the course of one
-        // request so use the query string as the key. We were using the 
-        // IssueSearch returned by getNewSearch as the key, but we have to
-        // call user.getMostRecentQuery prior to getNewSearch, so using
-        // that instead.
-        String queryString = ((ScarabUser)data.getUser()).getMostRecentQuery();
-        IteratorWithSize results = null;
-        Object obj = 
-            ScarabCache.get(queryString, "getUnprotectedCurrentSearchResults");
-        if (obj == null) 
+        String currentQueryString = ((ScarabUser)data.getUser()).getMostRecentQuery();
+        String sortColumn = data.getParameters().getString("sortColumn");
+        String sortInternal=data.getParameters().getString("sortInternal");
+        String sortPolarity = data.getParameters().getString("sortPolarity");
+        String currentQueryAddition = "" + sortColumn + sortInternal + sortPolarity;
+        String cachedQueryAddition = (String)data.getUser().getTemp("queryAddition");
+        if(currentQueryAddition.equals("nullnullnull"))
+            currentQueryAddition = cachedQueryAddition;
+
+        
+        List queryResult = (List)data.getUser().getTemp("queryResult");
+        
+        if (cachedQueryAddition==null || !cachedQueryAddition.equals(currentQueryAddition) || queryResult==null) 
         {       
-            results = getUncachedCurrentSearchResults();
-            ScarabCache.put(results, queryString, 
-                            "getUnprotectedCurrentSearchResults");
-        }
-        else 
-        {
-            results = (IteratorWithSize)obj;
-        }
-        return results;
+            queryResult = getSearchResults(currentQueryString);
+
+            data.getUser().setTemp("queryAddition", currentQueryAddition );
+            data.getUser().setTemp("queryResult", queryResult);
+        }    
+
+        return queryResult;
     }
 
     /**
-     * Performs search on current query (which is stored in user session).
+     * Performs search for a given queryString
      */
-    private IteratorWithSize getUncachedCurrentSearchResults()
+    private List getSearchResults(String queryString)
         throws Exception
     {
-        ScarabLocalizationTool l10n = getLocalizationTool();
-        ScarabUser user = (ScarabUser)data.getUser();
-        String currentQueryString = user.getMostRecentQuery();
-        IssueSearch search = getPopulatedSearch(currentQueryString);
-        IteratorWithSize queryResults = null;
+        IssueSearch search = getPopulatedSearch(queryString);
+        List queryResults = null;
 
-        // Do search
         try
         {
-            if (search == null) 
-            {
-                // an alert message should have been set while attempting
-                // to populate the search.
-                queryResults = IteratorWithSize.EMPTY;
-            }
-            else 
-            {
-                queryResults = search.getQueryResults(true);
-                if (!queryResults.hasNext())
-                {
-                    setInfoMessage(L10NKeySet.NoMatchingIssues);
-                }
-            }
-        }
-        catch (ScarabException e)
-        {
-            String queryError = e.getMessage();
-            if (queryError.startsWith(SearchIndex.PARSE_ERROR)) 
-            {
-                Log.get().info(queryError);
-                setAlertMessage(new SimpleSkipFiltering(
-                    l10n.format("QueryParserError", 
-                        new SnippetRenderer(data, "TextQueryHelp.vm"))));
-            }
-            else 
-            {
-                throw e; //EXCEPTION
-            }
+            	queryResults = search.getQueryResults();
         }
         finally
         {
@@ -2014,180 +1871,71 @@
     }
 
     /**
-     * Gets the number of results for the current query.  Looks first
-     * at the URL, then re-queries if size information is missing.
+     * Gets the number of results for the current query.     
      */
     public int getCurrentSearchResultsSize()
     {
-        String[] prevNextList = data.getParameters().getStrings("issueList");
-        int result = 0;
-        if (prevNextList == null) 
-        {
-            result = getCurrentSearchResults().size();
-        }
-        else 
-        {
-            result = Integer.parseInt(prevNextList[1]);
-        }
-        return result;
+        return getCurrentSearchResults().size();
     }
 
+    public boolean isIssuePartOfList()
+    {
+       return getIssuePosInList()!=-1;
+    }
     /**
      * Returns the issue's position (1-based) in current issue list.
      */
     public int getIssuePosInList()
-        throws Exception, ScarabException
     {
-        int issuePos = -1;
-        String id = getIssue().getUniqueId();
-        String[] prevNextList = data.getParameters().getStrings("issueList");
-        if (prevNextList != null) 
-        {
-            int listOffset = Math.max(0, Integer.parseInt(prevNextList[0]));
-            for (int i=2; i<prevNextList.length; i++)
-            {
-                if (prevNextList[i].equals(id)) 
-                {
-                    issuePos = listOffset + i - 1;
-                    break;
-                }
-            }        
-        }
-
-        return (issuePos <= 0) ? 1 : issuePos;
+        return data.getParameters().getInt(POS_IN_LIST, -1);
     }
 
+    public int getNextIssuePosInList()
+    {
+        return getIssuePosInList() + 1;
+    }
     /**
      * Returns next issue id in list.
      */
     public String getNextIssue()
-        throws Exception, ScarabException
+        throws TorqueException
     {
         String nextIssueId = null;
-        String[] prevNextList = data.getParameters().getStrings("issueList");
-        if (prevNextList != null) 
+        int nextIssueIndex = getNextIssuePosInList() - 1;
+        List searchResults = getCurrentSearchResults();
+        if(nextIssueIndex>=0 && nextIssueIndex< searchResults.size() )
         {
-            String id = getIssue().getUniqueId();
-            for (int i=2; i<prevNextList.length-1; i++)
-            {
-                if (prevNextList[i].equals(id)) 
-                {
-                    nextIssueId = prevNextList[i+1];
-                    break;
-                }
-            }
-        }
-        
-        if (nextIssueId == null) 
-        {
-            if (cachedNextIssueId == null) 
-            {
-                int issuePos = getIssuePosInList();
-                if (issuePos <= getCurrentSearchResultsSize())
-                {
-                    resetIssueIdList(issuePos);
-                    nextIssueId = cachedNextIssueId;
-                }
-            }
-            else 
-            {
-                nextIssueId = cachedNextIssueId;
-            }
+            nextIssueId = ((QueryResult)searchResults.get(nextIssueIndex)).getUniqueId();
         }
         return nextIssueId;
     }
 
+    public int getPrevIssuePosInList()
+    {
+        return getIssuePosInList() - 1;
+    }
     /**
      * Returns previous issue id in list.
      */
     public String getPrevIssue()
-        throws Exception, ScarabException
+    throws TorqueException
     {
         String prevIssueId = null;
-        String[] prevNextList = data.getParameters().getStrings("issueList");
-        if (prevNextList != null) 
-        {
-            String id = getIssue().getUniqueId();
-            for (int i=3; i<prevNextList.length; i++)
-            {
-                if (prevNextList[i].equals(id)) 
-                {
-                    prevIssueId = prevNextList[i-1];
-                    break;
-                }
-            }
-        }
-        
-        if (prevIssueId == null) 
+        int prevIssueIndex = getPrevIssuePosInList() - 1;
+        List searchResults = getCurrentSearchResults();
+        if(prevIssueIndex>=0 && prevIssueIndex<searchResults.size() )
         {
-            if (cachedPrevIssueId == null) 
-            {
-                int issuePos = getIssuePosInList();
-                if (issuePos > 1)
-                {
-                    resetIssueIdList(issuePos);
-                    prevIssueId = cachedPrevIssueId;
-                }
-            }
-            else 
-            {
-                prevIssueId = cachedPrevIssueId;
-            }
+            prevIssueId = ((QueryResult)searchResults.get(prevIssueIndex)).getUniqueId();
         }
         return prevIssueId;
     }
 
-    private void resetIssueIdList(int issuePos)
-    {
-        IteratorWithSize idList = getCurrentSearchResults();
-        ParameterParser pp = data.getParameters();
-        pp.remove("issueList");
-        int min = issuePos - 5;
-        int max = issuePos + 10;
-        pp.add("issueList", min);
-        pp.add("issueList", idList.size());
-
-        int count;
-        for (count = 0; idList.hasNext() && count < min; count++) 
-        {
-            idList.next();
-        }
-        for (; idList.hasNext() && count < issuePos - 2; count++) 
-        {
-            pp.add("issueList",
-                   ((QueryResult) idList.next()).getUniqueId());
-        }
-        if (idList.hasNext()) 
-        {
-            cachedPrevIssueId = ((QueryResult)idList.next())
-                .getUniqueId();                        
-            pp.add("issueList", cachedPrevIssueId);
-        }
-        if (idList.hasNext()) 
-        {
-            pp.add("issueList",
-                   ((QueryResult) idList.next()).getUniqueId());
-        }
-        if (idList.hasNext()) 
-        {
-            cachedNextIssueId = ((QueryResult)idList.next())
-                .getUniqueId();                        
-            pp.add("issueList", cachedNextIssueId);
-        }
-        for (count += 3; idList.hasNext() && count < max; count++) 
-        {
-            pp.add("issueList",
-                   ((QueryResult) idList.next()).getUniqueId());
-        }
-    }
-
     /**
      * Attempts to parse a date passed in the query page.
     */
-    private int checkDate(IssueSearch search, Field dateField)
-        throws Exception
+    private boolean validateDateFormat(IssueSearch search, Field dateField)
     {
-        int errorCount = 0;
+        boolean valid = true;
         try
         {
         	String date = dateField.toString();
@@ -2195,10 +1943,10 @@
         }
         catch (Exception e)
         {
-            errorCount = 1;
+            valid = false;
             dateField.setMessage("format error ["+e.getMessage()+"]");
         }
-        return errorCount;
+        return valid;
     }
 
 
@@ -2588,62 +2336,20 @@
      */
     public List getPaginatedList(List fullList, int pgNbr, int nbrItmsPerPage)
     {
-        List pageResults = null;
-        try 
+        List page = null;
+        if (nbrItmsPerPage < 0) 
         {
-            if (nbrItmsPerPage < 0) 
-            {
-                pageResults = fullList;
-            }
-            else 
-            {
-                this.nbrPages =  (int)Math.ceil((float)fullList.size() 
-                                                / nbrItmsPerPage);
-                this.nextPage = pgNbr + 1;
-                this.prevPage = pgNbr - 1;
-                pageResults = fullList.subList ((pgNbr - 1) * nbrItmsPerPage, 
-                    Math.min(pgNbr * nbrItmsPerPage, fullList.size()));
-            }
+            page = fullList;
         }
-        catch(Exception e)
-        {
-            Log.get().error("", e);
-        }
-        return pageResults;
-    }
-
-    /**
-     * Return a subset of the passed-in list.
-     * 
-     * @param nbrItmsPerPage negative value returns full list
-     */
-    public IteratorWithSize getPaginatedIterator(IteratorWithSize fullList, 
-                                                 int pgNbr, 
-                                                 int nbrItmsPerPage)
-    {
-        IteratorWithSize pageResults;
-        try 
-        {
-            if (nbrItmsPerPage < 0) 
-            {
-                pageResults = fullList;
-            }
-            else 
-            {
-                this.nbrPages =  (int)Math.ceil((float)fullList.size() 
-                                                / nbrItmsPerPage);
-                this.nextPage = pgNbr + 1;
-                this.prevPage = pgNbr - 1;
-                pageResults = new SubsetIteratorWithSize(
-                    fullList, (pgNbr - 1) * nbrItmsPerPage, nbrItmsPerPage); 
-            }
-        }
-        catch(Exception e)
+        else 
         {
-            Log.get().error("", e);
-            pageResults = IteratorWithSize.EMPTY;
+            this.nbrPages =  (int)Math.ceil((float)fullList.size() / nbrItmsPerPage);
+            this.nextPage = pgNbr + 1;
+            this.prevPage = pgNbr - 1;
+            page = fullList.subList ((pgNbr - 1) * nbrItmsPerPage, 
+                Math.min(pgNbr * nbrItmsPerPage, fullList.size()));
         }
-        return pageResults;
+        return page;
     }
 
     /**
@@ -3176,35 +2882,29 @@
         this.alertMessage = new SimpleSkipFiltering(localizable.getMessage(l10n));
     }
 
-    public IssueListIterator getIssueListIterator(IteratorWithSize iterator, 
-                                                  int listOffset, int size)
+    public IssueListIterator getIssueListIterator(List issueList, int pageNum, int resultsPerPage )
     {
-        return new IssueListIterator(iterator, listOffset, size);
+        return new IssueListIterator(issueList, pageNum, resultsPerPage);
     }
 
     public class IssueListIterator implements Iterator
     {
-        private static final String ISSUE_LIST = "issueList";
-        private static final int PREV_SIZE = 1;
-        private static final int NEXT_SIZE = 2;
-
-        private WindowIterator i;
-        private int size;
         private int listOffset;
-        private int count = -1;
+        private int count = 0;
+        private Iterator i;
+        private Object current = null;
 
-        private IssueListIterator(IteratorWithSize iterator, 
-                                  int listOffset, int size)
+        private IssueListIterator(List issueList, int pageNum, int resultsPerPage)
         {
-            this.listOffset = Math.max(listOffset, 0);
-            this.size = size;
-            this.i = new WindowIterator(iterator, PREV_SIZE, NEXT_SIZE);
+            this.listOffset = (pageNum - 1) * resultsPerPage;
+            this.i = issueList.iterator();
         }
 
         public Object next()
         {
             count++;
-            return i.next();
+            current = i.next();
+            return current;
         }
 
         public boolean hasNext()
@@ -3218,28 +2918,12 @@
         }
 
         public void initializeLink(ScarabLink link)
+            throws org.apache.torque.TorqueException
         {
-            link.setPage("ViewIssue.vm")
-                .addPathInfo("id", 
-                             ((QueryResult)i.get(0)).getUniqueId());
             int offset = listOffset + count;
-            for (int m = -1 * PREV_SIZE; m < 0; m++) 
-            {
-                if (i.hasValue(m)) 
-                {
-                    offset--;
-                }
-            }
-            link.addPathInfo(ISSUE_LIST, offset);
-            link.addPathInfo(ISSUE_LIST, size);
-            for (int m = -1 * PREV_SIZE; m <= NEXT_SIZE; m++) 
-            {
-                if (i.hasValue(m)) 
-                {
-                    link.addPathInfo(ISSUE_LIST,
-                                     ((QueryResult)i.get(m)).getUniqueId());
-                }
-            }
+            link.setPage("ViewIssue.vm")
+                .addPathInfo("id", ((QueryResult)current).getUniqueId())
+                .addPathInfo(POS_IN_LIST, offset);
         }
     } 
 
@@ -3478,8 +3162,12 @@
     public RModuleIssueType getRModuleIssueType(Integer moduleId, Integer issueTypeId) throws Exception
     {
         return RModuleIssueTypePeer.retrieveByPK(moduleId, issueTypeId);
-    } 
+    }
 
+    public void clearCachedQueryResult()
+    {
+        data.getUser().removeTemp("queryResult");
+    }     
 }
 
 

Modified: trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java&p2=trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java	(original)
+++ trunk/src/java/org/tigris/scarab/tools/localization/L10NKeySet.java	2007-06-09 08:06:34-0700
@@ -473,5 +473,6 @@
     public static final LocalizationKey CreatedDate = new L10NKey("CreatedDate");
     public static final LocalizationKey ModifiedBy = new L10NKey("ModifiedBy");
     public static final LocalizationKey ModifiedDate = new L10NKey("ModifiedDate");
+    public static final LocalizationKey Module = new L10NKey("Module");
     
 }

Modified: trunk/src/java/org/tigris/scarab/util/ScarabConstants.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/ScarabConstants.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/util/ScarabConstants.java&p2=trunk/src/java/org/tigris/scarab/util/ScarabConstants.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/ScarabConstants.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/ScarabConstants.java	2007-06-09 08:06:34-0700
@@ -232,11 +232,6 @@
      */
     final String ISSUE_VIEW_ALL = "all";
 
-    /** 
-     * list of invalid characters when doing searches
-     */
-    final String INVALID_SEARCH_CHARACTERS = "\"\t(){}[]!,;:?./*-+=+&|<>\\~^";
-
     /**
      * format for displaying dates
      */
@@ -283,12 +278,6 @@
     
     final Integer INTEGER_0 = new Integer(0);
 
-    //int QUERY_MAX_FILTER_CRITERIA = 
-    //    Turbine.getConfiguration().getInt("scarab.query.max.filter_criteria", 10);
-    final int QUERY_MAX_FILTER_CRITERIA = 10;
-    final int QUERY_MAX_JOIN = 31; 
-        //Turbine.getConfiguration().getInt("scarab.query.max.join", 31);
-
     /**
      * The maximum number of issues for batch view of detail.
      */
@@ -316,8 +305,7 @@
     /**
      * The maximumn number of report headings
      */
-    final int REPORT_MAX_CRITERIA = 
-        Turbine.getConfiguration().getInt("scarab.report.max.criteria", 5);
+    final int REPORT_MAX_CRITERIA = 5;
 
     /**
      * The default comment rendering engine

Removed: trunk/src/java/org/tigris/scarab/util/SubsetIterator.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/SubsetIterator.java?view=auto&rev=10444

Removed: trunk/src/java/org/tigris/scarab/util/SubsetIteratorWithSize.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/SubsetIteratorWithSize.java?view=auto&rev=10444

Removed: trunk/src/java/org/tigris/scarab/util/word/ComplexQueryException.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/ComplexQueryException.java?view=auto&rev=10444

Modified: trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java&p2=trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/IssueSearch.java	2007-06-09 08:06:34-0700
@@ -47,14 +47,11 @@
  */ 
 
 // JDK classes
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.AbstractList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -62,23 +59,20 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+import com.workingdogs.village.Record;
+import com.workingdogs.village.DataSetException;
 
-import org.apache.commons.collections.map.LRUMap;
 import org.apache.commons.collections.map.LinkedMap;
-import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.fulcrum.localization.Localization;
-import org.apache.fulcrum.parser.StringValueParser;
-import org.apache.log4j.Logger;
-import org.apache.torque.Torque;
 import org.apache.torque.TorqueException;
-import org.apache.torque.adapter.DB;
-import org.apache.torque.om.ComboKey;
-import org.apache.torque.om.ObjectKey;
-import org.apache.torque.om.SimpleKey;
 import org.apache.torque.util.Criteria;
+import org.apache.torque.util.SqlEnum;
+import org.apache.fulcrum.intake.Retrievable;
 import org.tigris.scarab.attribute.DateAttribute;
 import org.tigris.scarab.attribute.OptionAttribute;
 import org.tigris.scarab.attribute.StringAttribute;
@@ -87,28 +81,30 @@
 import org.tigris.scarab.om.AttachmentTypePeer;
 import org.tigris.scarab.om.Attribute;
 import org.tigris.scarab.om.AttributeManager;
+import org.tigris.scarab.om.AttributeOption;
 import org.tigris.scarab.om.AttributeValue;
 import org.tigris.scarab.om.AttributeValuePeer;
 import org.tigris.scarab.om.Issue;
 import org.tigris.scarab.om.IssuePeer;
 import org.tigris.scarab.om.IssueType;
+import org.tigris.scarab.om.IssueTypePeer;
 import org.tigris.scarab.om.MITList;
-import org.tigris.scarab.om.MITListItem;
+import org.tigris.scarab.om.MITListManager;
 import org.tigris.scarab.om.Module;
-import org.tigris.scarab.om.ModuleManager;
-import org.tigris.scarab.om.RModuleIssueType;
-import org.tigris.scarab.om.RModuleIssueTypeManager;
+import org.tigris.scarab.om.ScarabModulePeer;
 import org.tigris.scarab.om.RModuleOption;
 import org.tigris.scarab.om.RModuleOptionPeer;
 import org.tigris.scarab.om.RModuleUserAttribute;
 import org.tigris.scarab.om.ScarabUser;
+import org.tigris.scarab.om.ScarabUserImplPeer;
+import org.tigris.scarab.om.ScarabUserManager;
 import org.tigris.scarab.services.security.ScarabSecurity;
 import org.tigris.scarab.tools.ScarabLocalizationTool;
 import org.tigris.scarab.tools.localization.L10NKeySet;
-import org.tigris.scarab.util.IteratorWithSize;
-import org.tigris.scarab.util.Log;
 import org.tigris.scarab.util.ScarabConstants;
 import org.tigris.scarab.util.ScarabException;
+import org.tigris.scarab.search.CachedQuery;
+import org.tigris.scarab.search.CachedResultList;
 
 /** 
  * A utility class to build up and carry out a search for 
@@ -118,149 +114,47 @@
  * @author <a href="mailto:[email protected]">John McNally</a>
  * @version $Id$
  */
-public class IssueSearch 
-    extends Issue
+public class IssueSearch
+    implements Retrievable
 {
-    private static final int MAX_INNER_JOIN = 
-        ScarabConstants.QUERY_MAX_FILTER_CRITERIA;
+    private static final String STATE_CHANGE_DATE_TABLE = "STATE_CHANGE_DATE_TABLE";
+
+	private static final String STATE_CHANGE_TABLE = "STATE_CHANGE_TABLE";
+
+	private static final String SORT_HELP_TABLE = "SORT_HELP_TABLE";
+
+	private static final String SORT_TABLE = "SORT_TABLE";
 
-    private static final int MAX_JOIN = 
-        ScarabConstants.QUERY_MAX_JOIN;
 
     public static final String ASC = "asc";
     public static final String DESC = "desc";
 
     public static final String CREATED_BY_KEY = "created_by";
     public static final String ANY_KEY = "any";
-
-    // column names only
-    private static final String AV_OPTION_ID = 
-        AttributeValuePeer.OPTION_ID.substring(
-        AttributeValuePeer.OPTION_ID.indexOf('.')+1);
-    private static final String AV_ISSUE_ID = 
-        AttributeValuePeer.ISSUE_ID.substring(
-        AttributeValuePeer.ISSUE_ID.indexOf('.')+1);
-
-    private static final String ACTIVITYSETALIAS = "srchcobyactset";
-    private static final String ACTIVITYSETALIAS_MODIFICATION = "srchcobyactsetmodif";
-    private static final String ACTIVITYALIAS = "srchcobyact";
-
-    private static final String CREATED_BY = "CREATED_BY";
-    private static final String CREATED_DATE = "CREATED_DATE";
-    private static final String ATTRIBUTE_ID = "ATTRIBUTE_ID";
-    private static final String AND = " AND ";
-    private static final String OR = " OR ";
-    private static final String INNER_JOIN = " INNER JOIN ";
-    private static final String ON = " ON (";
-    private static final String IN = " IN (";
-    private static final String IS_NULL = " IS NULL";
-    private static final String LEFT_OUTER_JOIN = " LEFT OUTER JOIN ";
-    private static final String SELECT_DISTINCT = "select DISTINCT ";
-    
-    private static final String ACTSET_TRAN_ID = 
-        ActivitySetPeer.TRANSACTION_ID.substring(
-        ActivitySetPeer.TRANSACTION_ID.indexOf('.')+1);
-    private static final String 
-        ISSUEPEER_TRAN_ID__EQUALS__ACTIVITYSETALIAS_TRAN_ID =
-        IssuePeer.CREATED_TRANS_ID + '=' + 
-        ACTIVITYSETALIAS + '.' + ACTSET_TRAN_ID;
-    private static final String ACTSET_CREATED_BY = 
-        ActivitySetPeer.CREATED_BY.substring(
-        ActivitySetPeer.CREATED_BY.indexOf('.')+1);
-    private static final String ACTSET_CREATED_DATE = 
-        ActivitySetPeer.CREATED_DATE.substring(
-        ActivitySetPeer.CREATED_DATE.indexOf('.')+1);
-    private static final String ACTSET_MODIFIED_BY = 
-        ActivitySetPeer.CREATED_BY.substring(
-        ActivitySetPeer.CREATED_BY.indexOf('.')+1) + " as MODIFIED_BY";
-    private static final String ACTSET_MODIFIED_DATE = 
-        ActivitySetPeer.CREATED_DATE.substring(
-        ActivitySetPeer.CREATED_DATE.indexOf('.')+1) + " as MODIFIED_DATE";
-    private static final String ACT_ISSUE_ID = 
-        ActivityPeer.ISSUE_ID.substring(ActivityPeer.ISSUE_ID.indexOf('.')+1);
-    private static final String ACTIVITYALIAS_ISSUE_ID =
-        ACTIVITYALIAS + '.' + ACT_ISSUE_ID;
-    private static final String 
-        ACTIVITYALIAS_ISSUE_ID__EQUALS__ISSUEPEER_ISSUE_ID =
-        ACTIVITYALIAS_ISSUE_ID + '=' + IssuePeer.ISSUE_ID;
-    private static final String END_DATE = 
-        ActivityPeer.END_DATE.substring(
-        ActivityPeer.END_DATE.indexOf('.')+1);
-
-    private static final String AV_ATTR_ID = 
-        AttributeValuePeer.ATTRIBUTE_ID.substring(
-        AttributeValuePeer.ATTRIBUTE_ID.indexOf('.')+1);
-
-    private static final String ACT_NEW_USER_ID = 
-        ActivityPeer.NEW_USER_ID.substring(
-        ActivityPeer.NEW_USER_ID.indexOf('.')+1);
-    private static final String ACTIVITYALIAS_NEW_USER_ID =
-        ACTIVITYALIAS + '.' + ACT_NEW_USER_ID;
-
-    private static final String WHERE = " WHERE ";
-    private static final String FROM = " FROM ";
-    private static final String ORDER_BY = " ORDER BY ";
-    private static final String BASE_OPTION_SORT_LEFT_JOIN = 
-        " LEFT OUTER JOIN " + RModuleOptionPeer.TABLE_NAME + " sortRMO ON " +
-        '(' + IssuePeer.MODULE_ID + "=sortRMO.MODULE_ID AND " +
-        IssuePeer.TYPE_ID + "=sortRMO.ISSUE_TYPE_ID AND sortRMO.OPTION_ID=";
-    private static final String AV = "av";
-    private static final String DOT_OPTION_ID_PAREN = ".OPTION_ID)";
-    private static final String DOT_VALUE = ".VALUE";
-    private static final String SORTRMO_PREFERRED_ORDER = 
-        "sortRMO.PREFERRED_ORDER";
-
+    public static final String SEARCHING_USER_KEY = "$me";
+    private static ScarabUser searchingUserPlaceholder;
 
     private static final Integer NUMBERKEY_0 = new Integer(0);
+    
+    private static final char DOT_REPLACEMENT_IN_JOIN_CONDITION = '#';
 
-    /**
-     * The managed database connection used while iterating over large
-     * query result sets using a cursor.  This connection <b>must</b>
-     * be explicitly closed when done with it (e.g. at the end of the
-     * request)!
-     */
-    private Connection conn;
-
-    /**
-     * The statement that will be used by the connection to get the issue
-     * ids for the query.
-     */
-    private Statement searchStmt; 
-    /**
-     * The ResultSet(s) that contains the issue ids for a query.
-     */
-    private ResultSet searchRS;
-
-    /**
-     * The statement(s) that will be used by the connection to obtain the
-     * ResultSet for column data to be shown for the query.  Statements should
-     * be closed when no longer needed. Closing a Statement will release any 
-     * associated ResultSets for a compliant jdbc driver, but we don't rely 
-     * on this behavior.
-     */
-    private List stmtList;
-    /**
-     * The ResultSet(s) that contain query result column data.  We store the 
-     * size along with the RS in a ResultSetAndSize object, where size is
-     * the number of columns in the RS.
-     */
-    private List rsList;
-
-    /**
-     * used to track how long we hold the connection
-     */
-    private long connectionStartTime;
-
-    private SimpleDateFormat formatter;
+	private static final Pattern RELATIVE_DATE_PATTERN = Pattern.compile(
+        "\\s*now\\s*(-\\s*(\\d+)|)\\s*",
+		Pattern.CASE_INSENSITIVE
+    );
+	
+	private SimpleDateFormat formatter;
 
+    private ScarabUser searchingUser;
     private String searchWords;
     private String commentQuery;
     private Integer[] textScope;
     private String minId;
     private String maxId;
-    private String minDate;
-    private String maxDate;
-    private int minVotes;
+    private String minCreationDate;
+    private String maxCreationDate;
+    private String minChangeDate;
+    private String maxChangeDate;
     
     private Integer stateChangeAttributeId;
     private Integer stateChangeFromOptionId;
@@ -276,33 +170,18 @@
     private String sortInternalAttribute;
     private String sortPolarity;
     private MITList mitList;
-
-    private List userIdList;
-    private List userSearchCriteriaList;
-    private List lastUsedAVList;
-    private boolean modified;
-
-    private int lastTotalIssueCount = -1;
-    private IteratorWithSize lastQueryResults = null;
-
-    // the attribute columns that will be shown
+    private Map searchUsers = new HashMap();
+    private boolean mergePartialTextQueries = false;
+    
     private List issueListAttributeColumns;
 
-    // used to cache a few modules and issuetypes to make listing
-    // a result set faster.
-    private LRUMap moduleMap = new LRUMap(20);
-    private LRUMap rmitMap = new LRUMap(20);
-
     private boolean isSearchAllowed = true;
-
-    /** A counter of inner joins used in a query */
-    private int joinCounter;
     
     /**
      * This is the locale that the search is currently running
      * under. We need it to parse the date attributes. It defaults
      * to the US locale as that was the behaviour before.
-     * @todo Ideally, the minDate, maxDate and others should
+     * @todo Ideally, the minCreationDate, maxCreationDate and others should
      * be Date objects, with the user of this class doing the
      * parsing itself. However, the intake tool is currently
      * configured to use this class directly. Hopefully when
@@ -311,53 +190,43 @@
      */
     private Locale locale = Locale.US;
     
-    private StringValueParser parser = null;
-    
     private ScarabLocalizationTool L10N = null;
     
-    private boolean isOperable = true;
+    private Issue searchIssue;
+    private Module singleModule;
+    private IssueType singleIssueType;
+    
+    IssueSearch(Module module, IssueType issueType, ScarabUser searcher)
+    	throws Exception
+    {
+    	this( MITListManager.getSingleItemList(module, issueType, searcher), searcher);
+    }
 
-    IssueSearch(Issue issue, ScarabUser searcher)
+	IssueSearch(Issue issue, ScarabUser searcher)
         throws Exception
     {
         this(issue.getModule(), issue.getIssueType(), searcher);
         
-        //
         // Make copies of the issue's attribute values so that
         // we can modify them later without affecting the issue
         // itself.
-        //
-        // @todo: This section of code is a result of SCB965.
-        // However, I think a more significant problem is that
-        // ReportIssue is modifying the search's attribute values
-        // directly. I believe this breaks some OO principle or
-        // other and should be resolved some time.
-        //
-        List issueAttributes = issue.getAttributeValues();
-        List searchAttributes = this.getAttributeValues();
+        List searchAttributes = searchIssue.getAttributeValues();
         
-        for (Iterator iter = issueAttributes.iterator(); iter.hasNext(); ) {
+        for (Iterator iter = issue.getAttributeValues().iterator(); iter.hasNext(); ) {
             AttributeValue value = (AttributeValue) iter.next();
             searchAttributes.add(value.copy());
         }
     }
 
-    IssueSearch(Module module, IssueType issueType, ScarabUser searcher)
-        throws Exception
-    {
-        super(module, issueType);
-        isSearchAllowed = 
-            searcher.hasPermission(ScarabSecurity.ISSUE__SEARCH, module); 
-    }
-
     IssueSearch(MITList mitList, ScarabUser searcher)
         throws Exception
     {
-        super();
+        searchingUser = searcher;
+        searchIssue = new Issue();
         if (mitList == null || mitList.size() == 0) 
         {
             throw new IllegalArgumentException("A non-null list with at" +
-               " least one item is required."); //EXCEPTION
+               " least one item is required.");
         }
 
         String[] perms = {ScarabSecurity.ISSUE__SEARCH};
@@ -365,41 +234,32 @@
             .getPermittedSublist(perms, searcher);
 
         isSearchAllowed = searchableList.size() > 0;
-        isSearchAllowed=true;
 
-        if (searchableList.isSingleModuleIssueType()) 
+        this.mitList = searchableList;   
+        if (searchableList.isSingleModule()) 
         {
-            MITListItem item = searchableList.getFirstItem();
-            setModuleId(item.getModuleId());
-            setTypeId(item.getIssueTypeId());
+        	singleModule = searchableList.getModule();
+        	searchIssue.setModule(singleModule);
         }
-        else 
+        if (searchableList.isSingleIssueType()) 
         {
-            this.mitList = searchableList;   
-            if (searchableList.isSingleModule()) 
-            {
-                setModule(searchableList.getModule());
-            }
-            if (searchableList.isSingleIssueType()) 
-            {
-                setIssueType(searchableList.getIssueType());
-            }
-        }        
-    }
-
-    public boolean isOperable()
-    {
-    	return isOperable;
+        	singleIssueType = searchableList.getIssueType();
+        	searchIssue.setIssueType(singleIssueType);
+        }
     }
     
-    /**
-     * The issue can be flagged as inoperable. This can happen when
-     * a syntax check on the search criteria fails (e.g. invalid syntax on Date patterns)
-     * @param state
-     */
-    public void setIsOperable(boolean state)
+    public static ScarabUser getSearchingUserPlaceholder()
+        throws TorqueException
     {
-    	isOperable = state;
+        if(searchingUserPlaceholder==null)
+        {
+            searchingUserPlaceholder = ScarabUserManager.getInstance();
+            searchingUserPlaceholder.setFirstName("");
+            searchingUserPlaceholder.setLastName(SEARCHING_USER_KEY);
+            searchingUserPlaceholder.setUserName(SEARCHING_USER_KEY);
+            searchingUserPlaceholder.setEmail("");
+        }
+        return searchingUserPlaceholder;
     }
     
     public Locale getLocale() {
@@ -412,7 +272,26 @@
 
     public boolean isXMITSearch()
     {
-        return mitList != null && !mitList.isSingleModuleIssueType();
+        return !mitList.isSingleModuleIssueType();
+    }
+
+    /**
+     * Remove special characters from the text values to be searched for
+     * to make the search less specific.
+     *
+     */
+    public void removeSpecialCharacters()
+        throws Exception
+    {
+        for (Iterator textAVs = getTextAttributeValues().iterator(); textAVs.hasNext();)
+        {
+            AttributeValue av = (AttributeValue)textAVs.next();
+            String s = av.getValue();
+            if (s!=null) 
+            {
+                av.setValue( s.replaceAll("[^\\w]+", " ").toLowerCase());       
+            }
+        }
     }
 
     /**
@@ -422,8 +301,6 @@
      */
     public void setIssueListAttributeColumns(List rmuas)
     {
-        //FIXME! implement logic to determine if a new search is required.
-        //HELP: John, would it be sufficient to set modified=true?
         issueListAttributeColumns = rmuas;
     }
 
@@ -431,36 +308,6 @@
     {
         return issueListAttributeColumns;
     }
-
-    public List getUserIdList()
-    {
-        return userIdList;
-    }
-
-    /**
-     * returns the list of attribute values
-     * for all attributes in the current module
-     * and defined for all currently searched issueTypes.
-     * @return
-     * @throws Exception
-     */
-    public LinkedMap getCommonAttributeValuesMap()
-    throws Exception
-    {
-        return internalGetAttributeValuesMap(true);
-    }
-    
-    /**
-     * returns the list of attribute values
-     * for all attributes in the current module.
-     * @return
-     * @throws Exception
-     */
-    public LinkedMap getAllAvailableAttributeValuesMap()
-    throws Exception
-    {
-        return internalGetAttributeValuesMap(false);
-    }
         
     /**
      * returns the list of attribute values
@@ -472,30 +319,9 @@
      * @return
      * @throws Exception
      */
-    private LinkedMap internalGetAttributeValuesMap(boolean commonOnly) throws Exception
-    {
-        LinkedMap result = null;
-        if (isXMITSearch()) 
-        {
-            result = getMITAttributeValuesMap(commonOnly);
-        }
-        else 
-        {
-            result = super.getModuleAttributeValuesMap(false);
-        }
-        return result;
-    }   
-
-    /**
-     * AttributeValues that are relevant to the issue's current module.
-     * Empty AttributeValues that are relevant for the module, but have 
-     * not been set for the issue are included.  The values are ordered
-     * according to the module's preference
-     */
-    private LinkedMap getMITAttributeValuesMap(boolean commonOnly) 
-        throws Exception
+    public Map getAttributeValuesMap(boolean commonOnly) throws Exception
     {
-    	LinkedMap result = null;
+       	Map result = null;
 
         List attributes;
         if(commonOnly)
@@ -507,7 +333,7 @@
             attributes = mitList.getAttributes(false,false);
         }
 
-        Map siaValuesMap = getAttributeValuesMap();
+        Map siaValuesMap = searchIssue.getAttributeValuesMap();
         if (attributes != null) 
         {
             result = new LinkedMap((int)(1.25*attributes.size() + 1));
@@ -523,14 +349,14 @@
                 else 
                 {
                     AttributeValue aval = AttributeValue
-                        .getNewInstance(attribute, this);
-                    addAttributeValue(aval);
+                        .getNewInstance(attribute, searchIssue);
+                    searchIssue.addAttributeValue(aval);
                     result.put(key, aval);
                 }
             }
         }
         return result;
-    }
+    }   
 
     /**
      * @return The list of attributes of type "user" for the module(s)
@@ -539,32 +365,13 @@
     public List getUserAttributes()
         throws Exception
     {
-        List result = null;
-        if (isXMITSearch()) 
-        {
-            result = mitList.getCommonUserAttributes(false);
-        }
-        else 
-        {
-            result = getModule().getUserAttributes(getIssueType(), false);
-        }
-        return result;        
+        return mitList.getCommonUserAttributes(false);
     } 
 
     public List getLeafRModuleOptions(Attribute attribute)
         throws Exception
     {
-        List result = null;
-        if (isXMITSearch()) 
-        {
-            result = mitList.getCommonLeafRModuleOptions(attribute);
-        }
-        else 
-        {
-            result = getModule()
-                .getLeafRModuleOptions(attribute, getIssueType());
-        }
-        return result;        
+        return mitList.getCommonLeafRModuleOptions(attribute);
     } 
 
     public List getCommonOptionTree(Attribute attribute)
@@ -596,14 +403,9 @@
      */
     public void setSearchWords(String  v) 
     {
-        if (!ObjectUtils.equals(v, this.searchWords)) 
-        {
-            modified = true;
-            this.searchWords = v;
-        }
+        this.searchWords = v;
     }
 
-    
     /**
      * Get the value of commentQuery.
      * @return value of commentQuery.
@@ -619,11 +421,7 @@
      */
     public void setCommentQuery(String  v) 
     {
-        if (!ObjectUtils.equals(v, this.commentQuery)) 
-        {
-            modified = true;
-            this.commentQuery = v;
-        }
+        this.commentQuery = v;
     }
     
     /**
@@ -681,45 +479,9 @@
     public void setTextScope(Integer[] v) 
         throws Exception
     {
-        if (v != null) 
-        {
-            for (int i=v.length-1; i>=0; i--) 
-            {
-                if (v[i].equals(NUMBERKEY_0)) 
-                {
-                    v = getTextScopeForAll();
-                    break;
-                }       
-            }
-        }
-
-        // note previous block may have made v == null though its not likely
-        // (don't replace the if with an else)
-        if (v == null) 
-        {
-            modified |= this.textScope != null;
-            this.textScope = null;
-        }
-        else if (this.textScope != null && this.textScope.length == v.length)
-        {
-            for (int i=v.length-1; i>=0; i--) 
-            {
-                if (!v[i].equals(this.textScope[i])) 
-                {
-                    modified = true;
-                    this.textScope = v;            
-                    break;
-                }       
-            }
-        }
-        else 
-        {
-            modified = true;
-            this.textScope = v;            
-        }
+        this.textScope = v;            
     }
 
-
     /**
      * Get the value of minId.
      * @return value of minId.
@@ -729,23 +491,26 @@
         return minId;
     }
     
+    private static String emptyString2null(String s)
+    {
+        if (s != null && s.length() == 0) 
+        {
+            return null;
+        }
+        else
+        {
+        	return s;
+        }
+    }
+    
     /**
      * Set the value of minId.
      * @param v  Value to assign to minId.
      */
     public void setMinId(String  v) 
     {
-        if (v != null && v.length() == 0) 
-        {
-            v = null;
-        }
-        if (!ObjectUtils.equals(v, this.minId)) 
-        {
-            modified = true;
-            this.minId = v;
-        }
+        this.minId = emptyString2null(v);
     }
-
     
     /**
      * Get the value of maxId.
@@ -762,94 +527,81 @@
      */
     public void setMaxId(String  v) 
     {
-        if (v != null && v.length() == 0) 
-        {
-            v = null;
-        }
-        if (!ObjectUtils.equals(v, this.maxId)) 
-        {
-            modified = true;
-            this.maxId = v;
-        }
+        this.maxId = emptyString2null(v);
     }
-    
-    
+        
     /**
-     * Get the value of minDate.
-     * @return value of minDate.
+     * Get the value of minCreationDate.
+     * @return value of minCreationDate.
      */
-    public String getMinDate() 
+    public String getMinCreationDate() 
     {
-        return this.minDate;
+        return this.minCreationDate;
     }
     
     /**
-     * Set the value of minDate.
-     * @param newMinDate  Value to assign to minDate.
+     * Set the value of minCreationDate.
+     * @param newMinCreationDate  Value to assign to minCreationDate.
      */
-    public void setMinDate(String newMinDate) 
+    public void setMinCreationDate(String newMinCreationDate) 
     {
-        if (newMinDate != null && newMinDate.length() == 0) 
-        {
-            newMinDate = null;
-        }
-        
-        if (!ObjectUtils.equals(newMinDate, this.minDate)) 
-        {
-            this.modified = true;
-            this.minDate = newMinDate;
-        }
+        this.minCreationDate = emptyString2null(newMinCreationDate);
     }
 
+    /**
+     * Get the value of maxCreationDate.
+     * @return value of maxCreationDate.
+     */
+    public String getMaxCreationDate() 
+    {
+        return this.maxCreationDate;
+    }
     
     /**
-     * Get the value of maxDate.
-     * @return value of maxDate.
+     * Set the value of maxCreationDate.
+     * @param newMaxCreationDate Value to assign to maxCreationDate.
      */
-    public String getMaxDate() 
+    public void setMaxCreationDate(String newMaxCreationDate) 
     {
-        return this.maxDate;
+        this.maxCreationDate = emptyString2null(newMaxCreationDate);
     }
     
     /**
-     * Set the value of maxDate.
-     * @param newMaxDate Value to assign to maxDate.
+     * Get the value of minCreationDate.
+     * @return value of minCreationDate.
      */
-    public void setMaxDate(String newMaxDate) 
+    public String getMinChangeDate() 
     {
-        if (newMaxDate != null && newMaxDate.length() == 0) 
-        {
-            newMaxDate = null;
-        }
-        
-        if (!ObjectUtils.equals(newMaxDate, this.maxDate)) 
-        {
-            this.modified = true;
-            this.maxDate = newMaxDate;
-        }
+        return this.minChangeDate;
     }
     
     /**
-     * Get the value of minVotes.
-     * @return value of minVotes.
+     * Set the value of minChangeDate.
+     * @param newMinChangeDate  Value to assign to minChangeDate.
      */
-    public int getMinVotes() 
+    public void setMinChangeDate(String newMinChangeDate) 
     {
-        return minVotes;
+        this.minChangeDate = emptyString2null(newMinChangeDate);
     }
+
     
     /**
-     * Set the value of minVotes.
-     * @param v  Value to assign to minVotes.
+     * Get the value of maxChangeDate.
+     * @return value of maxChangeDate.
      */
-    public void setMinVotes(int  v) 
+    public String getMaxChangeDate() 
     {
-        if (v != this.minVotes) 
-        {
-            modified = true;
-            this.minVotes = v;
-        }
-    }    
+        return this.maxChangeDate;
+    }
+    
+    /**
+     * Set the value of maxChangeDate.
+     * @param newMaxChangeDate Value to assign to maxChangeDate.
+     */
+    public void setMaxChangeDate(String newMaxChangeDate) 
+    {
+        this.maxChangeDate = emptyString2null(newMaxChangeDate);
+    }
 
 
     /**
@@ -867,11 +619,7 @@
      */
     public void setStateChangeAttributeId(Integer  v) 
     {
-        if (!ObjectUtils.equals(v, this.stateChangeAttributeId)) 
-        {
-            modified = true;
-            this.stateChangeAttributeId = v;
-        }
+        this.stateChangeAttributeId = v;
     }
         
     /**
@@ -889,11 +637,7 @@
      */
     public void setStateChangeFromOptionId(Integer  v) 
     {
-        if (!ObjectUtils.equals(v, this.stateChangeFromOptionId)) 
-        {
-            modified = true;
-            this.stateChangeFromOptionId = v;
-        }
+        this.stateChangeFromOptionId = v;
     }
     
     /**
@@ -911,11 +655,7 @@
      */
     public void setStateChangeToOptionId(Integer  v) 
     {
-        if (!ObjectUtils.equals(v, this.stateChangeToOptionId)) 
-        {
-            modified = true;
-            this.stateChangeToOptionId = v;
-        }
+        this.stateChangeToOptionId = v;
     }
 
     
@@ -934,16 +674,7 @@
      */
     public void setStateChangeFromDate(String fromDate) 
     {
-        if (fromDate != null && fromDate.length() == 0) 
-        {
-            fromDate = null;
-        }
-        
-        if (!ObjectUtils.equals(fromDate, this.stateChangeFromDate)) 
-        {
-            this.modified = true;
-            this.stateChangeFromDate = fromDate;
-        }
+        this.stateChangeFromDate = emptyString2null(fromDate);
     }
     
     
@@ -962,19 +693,9 @@
      */
     public void setStateChangeToDate(String toDate) 
     {
-        if (toDate != null && toDate.length() == 0) 
-        {
-            toDate = null;
-        }
-        
-        if (!ObjectUtils.equals(toDate, this.stateChangeToDate)) 
-        {
-            this.modified = true;
-            this.stateChangeToDate = toDate;
-        }
+        this.stateChangeToDate = emptyString2null(toDate);
     }
     
-    
     /**
      * Get the value of sortAttributeId.
      * @return value of SortAttributeId.
@@ -990,20 +711,12 @@
      */
     public void setSortAttributeId(Integer v) 
     {
-        if (!ObjectUtils.equals(v, this.sortAttributeId)) 
-        {
-            modified = true;
-            this.sortAttributeId = v;
-        }
+        this.sortAttributeId = v;
     }
     
     public void setSortInternalAttribute(String internal)
     {
-        if (!ObjectUtils.equals(internal, this.sortInternalAttribute)) 
-        {
-            modified = true;
-            this.sortInternalAttribute = internal;
-        }
+        this.sortInternalAttribute = internal;
     }
     
     public String getSortInternalAttribute()
@@ -1027,116 +740,33 @@
      */
     public void setSortPolarity(String  v) 
     {
-        if (!ObjectUtils.equals(v, this.sortPolarity)) 
-        {
-            modified = true;
-            this.sortPolarity = v;
-        }
+        this.sortPolarity = v;
     }
 
+    public Map getSearchUsers()
+    {
+    	return searchUsers;
+    }
+    
     /**
      * Describe <code>addUserSearch</code> method here.
      *
      * @param userId a <code>String</code> represention of the PrimaryKey
-     * @param searchCriteria a <code>String</code> either a String 
+     * @param attributeId a <code>String</code> either a String 
      * representation of an Attribute PrimaryKey, or the Strings "created_by" 
      * "any"
      */
-    public void addUserCriteria(String userId, String searchCriteria)
-    {
-        if (userId == null) 
-        {
-            throw new IllegalArgumentException("userId cannot be null."); //EXCEPTION
-        }
-        if (searchCriteria == null) 
-        {
-            searchCriteria = ANY_KEY;
-        }
-
-        if (userIdList == null) 
-        {
-            userIdList = new ArrayList(4);
-            userSearchCriteriaList = new ArrayList(4);
-        }
-        boolean newCriteria = true;
-        for (int i=userIdList.size()-1; i>=0 && newCriteria; i--) 
-        {
-            Object attrId = userSearchCriteriaList.get(i);
-            // not new if attrId already present or an ANY search has already
-            // been specified
-            newCriteria = !(userId.equals(userIdList.get(i)) && 
-               (searchCriteria.equals(attrId) || ANY_KEY.equals(attrId))); 
-        }
+    public void addUserSearch(String userId, String attributeId)
+    {        
+        Set attributeIds = (Set)searchUsers.get(userId);
         
-        if (newCriteria) 
-        {
-            modified = true;
-            // if the new criteria is ANY, then remove old criteria 
-            if (ANY_KEY.equals(searchCriteria)) 
-            {
-                for (int i=userIdList.size()-1; i>=0; i--) 
-                {
-                    if (userId.equals(userIdList.get(i)))
-                    {
-                        userIdList.remove(i);
-                        userSearchCriteriaList.remove(i);
-                    }
-                }
-            }
-            userIdList.add(userId);
-            userSearchCriteriaList.add(searchCriteria);
-        }
-    }
-
-    private boolean isAVListModified()
-        throws TorqueException
-    {
-        boolean result = false;
-        if (lastUsedAVList == null) 
-        {
-            result = true;
-        }
-        else 
-        {
-            List avList = getAttributeValues();
-            int max = avList.size();
-            if (lastUsedAVList.size() == max) 
-            {
-                for (int i=0; i<max; i++) 
-                {
-                    AttributeValue a1 = (AttributeValue)avList.get(i);
-                    AttributeValue a2 = (AttributeValue)lastUsedAVList.get(i);
-                    if (!ObjectUtils.equals(a1.getOptionId(), a2.getOptionId())
-                         || !ObjectUtils.equals(a1.getUserId(), a2.getUserId())
-                         //|| a1.getNumericValue() != a2.getNumericValue()
-                         || !ObjectUtils.equals(a1.getValue(), a2.getValue()))
-                    {
-                        result = true;
-                    }
-                }
-            }
-            else 
-            {
-                result = true;
-            }
-        }        
-        return result;
-    }
-
-    /**
-     * 
-     *
-     * @return a <code>boolean</code> value
-     */
-    private void checkModified()
-        throws TorqueException
-    {
-        if (modified || isAVListModified()) 
+        if(attributeIds==null)
         {
-            modified = false;
-            lastTotalIssueCount = -1;
-            lastQueryResults = null;
+            attributeIds=new HashSet();
+            searchUsers.put(userId, attributeIds);        
         }
+        
+        attributeIds.add(attributeId);
     }
 
     public Integer getALL_TEXT()
@@ -1159,13 +789,12 @@
     private List getTextAttributeValues(boolean quickSearchOnly)
         throws Exception
     {
-    	LinkedMap searchValues = getCommonAttributeValuesMap();
+    	Map searchValues = getAttributeValuesMap(true);
         List searchAttributes = new ArrayList(searchValues.size());
 
-        for (int i=0; i<searchValues.size(); i++) 
+        for (Iterator i=searchValues.values().iterator(); i.hasNext();) 
         {
-            AttributeValue searchValue = 
-                (AttributeValue)searchValues.getValue(i);
+            AttributeValue searchValue = (AttributeValue)i.next();
             if ((!quickSearchOnly || searchValue.isQuickSearchAttribute())
                  && searchValue.getAttribute().isTextAttribute()) 
             {
@@ -1185,53 +814,26 @@
     public List getQuickSearchOptionAttributeValues()
         throws Exception
     {
-        return getOptionAttributeValues(true);
+        Map searchValues = getAttributeValuesMap(true);
+		List searchAttributeValues = new ArrayList(searchValues.size());
+		
+		for (Iterator i= searchValues.values().iterator();i.hasNext();) 
+		{
+		    AttributeValue searchValue = (AttributeValue)i.next();
+		    if (searchValue.isQuickSearchAttribute()
+		         && searchValue instanceof OptionAttribute) 
+		    {
+		        searchAttributeValues.add(searchValue);
+		    }
+		}
+		
+		return searchAttributeValues;
     }
 
     /**
-     * Returns OptionAttributes which have been marked for Quick search.
+     * remove unset AttributeValues.
      *
-     * @return a <code>List</code> value
-     * @exception Exception if an error occurs
-     */
-    public List getOptionAttributeValues()
-        throws Exception
-    {
-        return getOptionAttributeValues(false);
-    }
-
-
-    /**
-     * Returns OptionAttributes which have been marked for Quick search.
-     *
-     * @return a <code>List</code> value
-     * @exception Exception if an error occurs
-     */
-    private List getOptionAttributeValues(boolean quickSearchOnly)
-        throws Exception
-    {
-    	LinkedMap searchValues = getCommonAttributeValuesMap();
-        List searchAttributeValues = new ArrayList(searchValues.size());
-
-        for (int i=0; i<searchValues.size(); i++) 
-        {
-            AttributeValue searchValue = 
-                (AttributeValue)searchValues.getValue(i);
-            if ((!quickSearchOnly || searchValue.isQuickSearchAttribute())
-                 && searchValue instanceof OptionAttribute) 
-            {
-                searchAttributeValues.add(searchValue);
-            }
-        }
-
-        return searchAttributeValues;
-    }
-
-
-    /**
-     * remove unset AttributeValues.
-     *
-     * @param attValues a <code>List</code> value
+     * @param attValues a <code>List</code> value
      */
     private List removeUnsetValues(List attValues)
     {
@@ -1248,99 +850,14 @@
         return setAVs;
     }
 
-
-    private void addAnd(StringBuffer sb)
-    {
-        if (sb.length() > 0) 
-        {
-            sb.append(AND);
-        }
-    }
-
-    private void addIssueIdRange(StringBuffer where)
-        throws ScarabException, Exception
-    {
-        // check limits to see which ones are present
-        // if neither are present, do nothing
-        if ((minId != null && minId.length() != 0)
-              || (maxId != null && maxId.length() != 0)) 
-        {
-            StringBuffer sb = new StringBuffer();
-            String domain = null;
-            String prefix = null;
-            Issue.FederatedId minFid = null;
-            Issue.FederatedId maxFid = null;
-            if (minId == null || minId.length() == 0) 
-            {
-                maxFid = new Issue.FederatedId(maxId);
-                setDefaults(null, maxFid);
-                addAnd(sb);
-                sb.append(IssuePeer.ID_COUNT).append("<=")
-                    .append(maxFid.getCount());
-                domain = maxFid.getDomain();
-                prefix = maxFid.getPrefix();
-            }
-            else if (maxId == null || maxId.length() == 0) 
-            {
-                minFid = new Issue.FederatedId(minId);
-                setDefaults(minFid, null);
-                addAnd(sb);
-                sb.append(IssuePeer.ID_COUNT).append(">=")
-                    .append(minFid.getCount());
-                domain = minFid.getDomain();
-                prefix = minFid.getPrefix();
-            }
-            else 
-            {
-                minFid = new Issue.FederatedId(minId);
-                maxFid = new Issue.FederatedId(maxId);
-                setDefaults(minFid, maxFid);
-                
-                // make sure min id is less than max id and that the character
-                // parts are equal otherwise skip the query, there are no 
-                // matches
-                if (minFid.getCount() <= maxFid.getCount() 
-                  && StringUtils.equals(minFid.getPrefix(), maxFid.getPrefix())
-                  && StringUtils.equals(minFid.getDomain(), maxFid.getDomain()))
-                {
-                    addAnd(sb);
-                    sb.append(IssuePeer.ID_COUNT).append(">=")
-                        .append(minFid.getCount()).append(AND)
-                        .append(IssuePeer.ID_COUNT).append("<=")
-                        .append(maxFid.getCount());
-                    domain = minFid.getDomain();
-                    prefix = minFid.getPrefix();
-                }
-                else 
-                {
-                    throw new ScarabException(L10NKeySet.ExceptionIncompatibleIssueIds,
-                            minId,
-                            maxId);
-                }
-            }
-            if (domain != null) 
-            {
-                sb.append(AND).append(IssuePeer.ID_DOMAIN).append("='")
-                    .append(domain).append('\'');
-            }
-            if (prefix != null) 
-            {
-                sb.append(AND).append(IssuePeer.ID_PREFIX).append("='")
-                    .append(prefix).append('\'');
-            }
-            where.append(AND).append(sb);
-        }
-    }
-
-
     /**
      * give reasonable defaults if module code was not specified
      */
-    private void setDefaults(FederatedId minFid, 
-                             FederatedId maxFid)
+    private void setDefaults(Issue.FederatedId minFid, 
+                             Issue.FederatedId maxFid)
         throws Exception
     {
-        Module module = getModule();
+        Module module = singleModule;
         if (module != null) 
         {
             if (minFid != null && minFid.getDomain() == null) 
@@ -1383,37 +900,30 @@
      * this flag is true, then 24 hours - 1 msec will be added to the date.
      * @return a <code>Date</code> value
      */
-    public Date parseDate(String dateString,
-                          boolean addTwentyFourHours)
+    public Date parseDate(String dateString, boolean addTwentyFourHours)
         throws ParseException
     {
         Date date = null;
         if (dateString != null) 
         {
-            if (dateString.indexOf(':') == -1)
+            Matcher m = RELATIVE_DATE_PATTERN.matcher(dateString);
+        	if(m.matches())
+        	{
+                date = new Date();
+        		String dateDifference = m.group(2);
+        		if(dateDifference!=null)
+        		{
+      				int hours = Integer.parseInt(dateDifference);
+       				date.setTime(date.getTime() - hours * 3600000 );
+        		}
+        	}
+            else if (dateString.indexOf(':') == -1)
             {
-                //
-                // First try to parse the date using the current
-                // locale. If that doesn't work, then try the
-                // ISO format.
-                //
                 String[] patterns = {
                     Localization.getString(this.locale, "ShortDatePattern"),
                     ScarabConstants.ISO_DATE_PATTERN };
                 date = parseDate(dateString, patterns);
                 
-                // one last try with the default locale format
-                if (date == null) 
-                {
-                    //
-                    // If this fails, then we want the parse exception
-                    // to propogate. That's why we don't use
-                    // parseDateWithFormat() here.
-                    //
-                    date = DateFormat.getDateInstance().parse(dateString);
-                }
-
-                // add 24 hours to max date so it is inclusive
                 if (addTwentyFourHours) 
                 {                
                     date.setTime(date.getTime() + 86399999);
@@ -1421,21 +931,10 @@
             }
             else
             {
-                //
-                // First try to parse the date using the current
-                // locale. If that doesn't work, then try the
-                // ISO format.
-                //
                 String[] patterns = {
                     Localization.getString(this.locale, "ShortDateTimePattern"),
                     ScarabConstants.ISO_DATETIME_PATTERN };
-                date = parseDate(dateString, patterns);
-        
-                // one last try with the default locale format
-                if (date == null) 
-                {
-                    date = DateFormat.getDateTimeInstance().parse(dateString);
-                }
+                date = parseDate(dateString, patterns);        
             }
         }
         
@@ -1449,8 +948,7 @@
      *
      * @param s a <code>String</code> value that should be converted
      * to a <code>Date</code>.
-     * @param patterns if no time is given in the date string and
-     * this flag is true, then 24 hours - 1 msec will be added to the date.
+     * @param patterns patterns to be used for conversion
      * @return the equivalent <code>Date</code> if the string could
      * be parsed. 
      * @throws ParseException if input String is null, or the string
@@ -1459,12 +957,9 @@
     private Date parseDate(String s, String[] patterns)
         throws ParseException
     {
-        /* FIXME: the contract for this method is strange
-           it is returning a null value when encountering a ParseException,
-           and throwing a ParseException when having a wrong input*/
         if (s == null) 
         {
-            throw new ParseException("Input string was null", -1); //EXCEPTION
+            throw new ParseException("Input string was null", -1);
         }
 
         if (formatter == null) 
@@ -1474,9 +969,16 @@
         
         for (int i = 0; i < patterns.length; i++) 
         {
-            formatter.applyPattern(patterns[i]);
-            Date date = parseDateWithFormat(s, formatter);
-            
+        	Date date = null;
+        	formatter.applyPattern(patterns[i]);
+            try
+            {
+            	date = formatter.parse(s);
+            }
+            catch (ParseException ex)
+            {
+                // ignore, because we have to try all patterns
+            }            
             if (date != null) 
             {
                 return date;
@@ -1484,155 +986,7 @@
         }
         
         throw new ParseException("Date could not be parsed with any"
-                                 + " of the provided date patterns.", -1); //EXCEPTION
-    }
-    
-    private Date parseDateWithFormat(String dateString, DateFormat format) {
-        try
-        {
-            return format.parse(dateString);
-        }
-        catch (ParseException ex)
-        {
-            return null;
-        }
-    }
-
-
-    private void addDateRange(String column, Date minUtilDate,
-                              Date maxUtilDate, StringBuffer sb)
-        throws Exception
-    {
-        // check limits to see which ones are present
-        // if neither are present, do nothing
-        if (minUtilDate != null || maxUtilDate != null) 
-        {
-            DB adapter = Torque.getDB(Torque.getDefaultDB());
-            if (minUtilDate == null) 
-            {
-                sb.append(column).append('<')
-                    .append(adapter.getDateString(maxUtilDate));
-            }
-            else if (maxUtilDate == null) 
-            {
-                sb.append(column).append(">=")
-                    .append(adapter.getDateString(minUtilDate));
-            }
-            else 
-            {
-                // make sure min id is less than max id and that the character
-                // parts are equal otherwise skip the query, there are no 
-                // matches
-                if (minUtilDate.before(maxUtilDate))
-                {
-                    sb.append(column).append(">=")
-                        .append(adapter.getDateString(minUtilDate));
-                    sb.append(AND);
-                    sb.append(column).append('<')
-                        .append(adapter.getDateString(maxUtilDate));
-                }
-                else 
-                {
-                    throw new ScarabException(L10NKeySet.ExceptionMaxdateBeforeMindate,
-                            this.maxDate,
-                            minUtilDate);
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Returns a List of matching issues.  if no OptionAttributes were
-     * found in the input list, criteria is unaltered.
-     *
-     * @param attValues a <code>List</code> value
-     */
-    private void addSelectedAttributes(StringBuffer fromClause, StringBuffer whereClause, 
-                                       List attValues, Set tableAliases)
-        throws Exception
-    {
-        Map attrMap = new HashMap((int)(attValues.size()*1.25));
-        for (int j=0; j<attValues.size(); j++) 
-        {
-            AttributeValue multiAV = (AttributeValue)attValues.get(j);
-            if (multiAV instanceof OptionAttribute)
-            {
-                Integer index = multiAV.getAttributeId();
-                List options = (List)attrMap.get(index);
-                if (options == null) 
-                {
-                    options = new ArrayList();
-                    attrMap.put(index, options);
-                }
-                
-                //pull any chained values out to create a flat list
-                List chainedValues = multiAV.getValueList();
-                for (int i=0; i<chainedValues.size(); i++) 
-                {
-                    AttributeValue aval = (AttributeValue)chainedValues.get(i);
-                    Integer optionId = aval.getOptionId();
-                    if(optionId == null)
-                    {
-                        continue;
-                    }
-                    if (optionId.intValue() != 0) // Empty value is 0
-                    {
-                        buildOptionList(options, aval);
-                    }
-                    else
-                    {
-                        options.add(optionId);
-                    }
-                    
-                }
-            }
-        }
-
-        for (Iterator i=attrMap.entrySet().iterator(); i.hasNext();) 
-        {
-            Map.Entry entry = (Map.Entry)i.next();
-            String alias = "av" + entry.getKey();
-            Integer key = (Integer) entry.getKey();
-            String c2 = null;
-            c2 = alias + '.' + AV_ATTR_ID + '=' + key;
-            joinCounter++;
-            String joinClause = LEFT_OUTER_JOIN + AttributeValuePeer.TABLE_NAME
-                + ' ' + alias + " ON (" + 
-                alias + '.' + AV_ISSUE_ID + '=' + IssuePeer.ISSUE_ID + 
-                AND + c2 + AND + 
-                alias + '.' + "DELETED=0" + ')';
-            if (whereClause.length() > 0)
-            {
-                whereClause.append(AND);
-            }
-            whereClause.append('(');
-            List options = (List) entry.getValue();
-            boolean bSearched = false;
-            if (options.size() == 1 && !(((Integer)options.get(0)).intValue()==0))
-            {
-                whereClause.append(alias + '.' + AV_OPTION_ID + '='
-                        + options.get(0));
-                bSearched = true;
-            }
-            if (options.size() > 1)
-            {
-                whereClause.append(alias + '.' + AV_OPTION_ID + " IN ("
-                        + StringUtils.join(options.iterator(), ",") + ')');
-                bSearched = true;
-            }
-            if (options.contains(new Integer(0))) //is 'empty' option selected?
-            {
-                if (bSearched)
-                {
-                    whereClause.append(OR);
-                }
-                whereClause.append(alias + '.' + AV_OPTION_ID + " IS NULL");
-            }
-            whereClause.append(')');
-            fromClause.append(joinClause);
-            tableAliases.add(alias);
-        }
+                                 + " of the provided date patterns.", -1);
     }
 
     /**
@@ -1667,46 +1021,15 @@
     private void buildOptionList(List options, AttributeValue aval)
         throws Exception
     {
-        List descendants = null;
-        // it would be a more correct query to separate the descendant
-        // options by module and do something like
-        // ... (module_id=1 and option_id in (1,2,3)) OR (module_id=5...
-        // but we are not checking which options are active here so i
-        // don't think the complexity of the query is needed.  might want
-        // to revisit, especially the part about ignoring active setting.
-        if (isXMITSearch()) 
-        {
-            descendants = 
-                mitList.getDescendantsUnion(aval.getAttributeOption());
-        }
-        else 
-        {
-            IssueType issueType = getIssueType();
-            
-            //
-            // This call checks whether the attribute value is available
-            // to the current module. If not, then no attribute options
-            // are added to the list.
-            //
-            RModuleOption rmo = getModule()
-                .getRModuleOption(aval.getAttributeOption(), issueType);
-            if (rmo != null) 
-            {
-                descendants = rmo.getDescendants(issueType);
-            }
-        }
+        List descendants =  mitList.getDescendantsUnion(aval.getAttributeOption());
         
-        //
         // Include the selected attribute value as one of the options
         // to search for.
-        //
         options.add(aval.getOptionId());
         
         if (descendants != null && !descendants.isEmpty())
         {
-            //
             // Add all applicable child attribute options to the list as well.
-            //
             for (Iterator i = descendants.iterator(); i.hasNext();) 
             {
                 options.add(((RModuleOption)i.next())
@@ -1715,237 +1038,14 @@
         }
     }
 
-    private void addUserAndCreatedDateCriteria(StringBuffer from, 
-                                               StringBuffer where)
-        throws Exception
-    {
-        String dateRangeSql = null;
-        if (getMinDate() != null || getMaxDate() != null) 
-        {
-            StringBuffer sbdate = new StringBuffer();
-            Date minUtilDate = parseDate(getMinDate(), false);
-            Date maxUtilDate = parseDate(getMaxDate(), true);
-            addDateRange(ACTIVITYSETALIAS + '.' + CREATED_DATE, 
-                         minUtilDate, maxUtilDate, sbdate);
-            dateRangeSql = sbdate.toString(); 
-        }                
-        
-        if (userIdList == null || userIdList.isEmpty())
-        {
-            if (dateRangeSql != null) 
-            {
-                joinCounter++;
-                // just dates
-                from.append(INNER_JOIN).append(ActivitySetPeer.TABLE_NAME) 
-                    .append(' ').append(ACTIVITYSETALIAS).append(ON).append(
-                    ISSUEPEER_TRAN_ID__EQUALS__ACTIVITYSETALIAS_TRAN_ID)
-                    .append(AND).append(dateRangeSql)
-                    .append(')');
-            }
-        }
-        else
-        {
-            List anyUsers = null;
-            List creatorUsers = null;
-            Map attrUsers = null;
-
-            int maxUsers = userIdList.size();
-            // separate users by attribute, Created_by, and Any
-            for (int i =0; i<maxUsers; i++)
-            {
-                String userId = (String)userIdList.get(i);
-                String attrId = (String)userSearchCriteriaList.get(i);
-                if (attrId == null || ANY_KEY.equals(attrId)) 
-                {
-                    if (anyUsers == null) 
-                    {
-                        anyUsers = new ArrayList(maxUsers);
-                    }
-                    anyUsers.add(userId);
-                }               
-                else if (CREATED_BY_KEY.equals(attrId)) 
-                {
-                    if (creatorUsers == null) 
-                    {
-                        creatorUsers = new ArrayList(maxUsers);
-                    }
-                    creatorUsers.add(userId);
-                }
-                else 
-                {
-                    // using a map here seems like overkill, but it
-                    // makes the logic easier
-                    if (attrUsers == null) 
-                    {
-                        attrUsers = new HashMap(maxUsers);
-                    }
-                    List userIds = (List)attrUsers.get(attrId);
-                    if (userIds == null) 
-                    {
-                        userIds = new ArrayList(maxUsers);
-                        attrUsers.put(attrId, userIds);
-                    }
-                    userIds.add(userId);
-                }
-            }
-
-            // All users are compared using OR, so use a single alias
-            // for activities related to users.
-            joinCounter++;
-            StringBuffer fromClause = new StringBuffer(100);
-            fromClause.append(INNER_JOIN).append(ActivityPeer.TABLE_NAME)
-                .append(' ').append(ACTIVITYALIAS).append(ON)
-                .append(ACTIVITYALIAS_ISSUE_ID__EQUALS__ISSUEPEER_ISSUE_ID);
-
-            StringBuffer attrCrit = null;
-            if (anyUsers != null) 
-            {
-                attrCrit = new StringBuffer(50);
-                attrCrit.append('(');
-                addUserActivityFragment(attrCrit, anyUsers);
-                attrCrit.append(')');
-            }
-            
-            // Add sql fragment for each attribute.  The sql is similar
-            // to the one used for Any users with the addition of attribute 
-            // criteria
-            if (attrUsers != null) 
-            {
-                for (Iterator i = attrUsers.entrySet().iterator(); i.hasNext();)
-                {
-                    if (attrCrit == null) 
-                    {
-                        attrCrit = new StringBuffer();
-                    }
-                    else 
-                    {
-                        attrCrit.append(OR);
-                    }
-                
-                    Map.Entry entry = (Map.Entry)i.next();
-                    String attrId = (String)entry.getKey();
-                    List userIds = (List)entry.getValue();
-                    attrCrit.append('(');
-                    addUserActivityFragment(attrCrit, userIds);
-                    attrCrit.append(AND +
-                        ACTIVITYALIAS + '.' + ATTRIBUTE_ID + '=' + attrId);
-                    attrCrit.append(')');
-                }
-            }
-
-            boolean isAddActivitySet = anyUsers != null || creatorUsers != null
-                || dateRangeSql != null;
-            String whereClause = null;
-            if (isAddActivitySet)
-            {
-                if (attrCrit != null) 
-                {
-                    whereClause = '(' + attrCrit.toString() + ')';
-                }
-
-                joinCounter++;
-                fromClause.append(')').append(INNER_JOIN)
-                    .append(ActivitySetPeer.TABLE_NAME) 
-                    .append(' ').append(ACTIVITYSETALIAS).append(ON).append(
-                    ISSUEPEER_TRAN_ID__EQUALS__ACTIVITYSETALIAS_TRAN_ID);
-
-                if (anyUsers != null || creatorUsers != null)
-                {
-                    List anyAndCreators = new ArrayList(maxUsers);
-                    if (anyUsers != null) 
-                    {
-                        anyAndCreators.addAll(anyUsers);
-                    }
-                    if (creatorUsers != null) 
-                    {
-                        anyAndCreators.addAll(creatorUsers);
-                    }
-
-                    // we can add this to the join condition, if created-only
-                    // query otherwise it needs to go in the where clause
-                    String createdBySqlFragment =  
-                        ACTIVITYSETALIAS + '.' + CREATED_BY;
-                    if (anyAndCreators.size() == 1) 
-                    {
-                        createdBySqlFragment += 
-                            '=' + anyAndCreators.get(0).toString();
-                    }
-                    else 
-                    {
-                        createdBySqlFragment += IN + 
-                            StringUtils.join(anyAndCreators.iterator(), ",") 
-                            + ')';
-                    }
-                
-                    if (anyUsers != null || attrUsers != null) 
-                    {
-                        fromClause.append(')'); 
-                        whereClause = '(' + whereClause + OR + 
-                            createdBySqlFragment + ')';
-                        if (dateRangeSql != null) 
-                        {
-                            whereClause += AND + dateRangeSql;
-                        }
-                    }
-                    else 
-                    {
-                        fromClause.append(AND).append(createdBySqlFragment);
-                        if (dateRangeSql != null) 
-                        {
-                            fromClause.append(AND).append(dateRangeSql);
-                        }
-                        fromClause.append(')'); 
-                    }
-                }
-                else // dateRangeSql will not be null
-                {
-                    fromClause.append(AND).append(dateRangeSql).append(')'); 
-                }                
-            }
-            else 
-            {
-                // we only had single-attribute users and no date criteria.
-                // attrCrit will not be null, because we had to have at
-                // least one user or we'd not be here
-                fromClause.append(AND).append('(').append(attrCrit)
-                    .append("))");
-            }
-
-            from.append(fromClause.toString());
-            if (whereClause != null) 
-            {
-                where.append(AND).append(whereClause);
-            }
-        }
-    }
-
-    private void addUserActivityFragment(StringBuffer sb, List userIds)
-    {
-        sb.append(ACTIVITYALIAS + '.' + END_DATE + 
-                  IS_NULL + AND + ACTIVITYALIAS_NEW_USER_ID);
-        if (userIds.size() == 1) 
-        {
-            sb.append('=').append(userIds.get(0));
-        }
-        else 
-        {
-            sb.append(IN + 
-                       StringUtils.join(userIds.iterator(), ",") + ')');
-        }
-    }
-
-
-    private Long[] getTextMatches(List attValues, boolean mergeTextResults)
+    private Long[] getTextMatches()
         throws Exception
     {
-        boolean searchCriteriaExists = false;
+        List setAttValues = getSetAttributeValues();
+    	boolean searchCriteriaExists = false;
         Long[] matchingIssueIds = null;
         SearchIndex searchIndex = SearchFactory.getInstance();
-        if (searchIndex == null)
-        {
-            // Check your configuration.
-            throw new Exception("No index available to search"); //EXCEPTION
-        }
+
         if (getSearchWords() != null && getSearchWords().length() != 0)
         {
             searchIndex.addQuery(getTextScope(), getSearchWords());
@@ -1953,37 +1053,45 @@
         }
         else 
         {
-            for (int i=0; i<attValues.size(); i++) 
+            for (int i=0; i<setAttValues.size(); i++) 
             {
-                AttributeValue aval = (AttributeValue)attValues.get(i);
-                if (aval.getValue() != null
-                        && aval.getValue().length() != 0)
+                AttributeValue aval = (AttributeValue)setAttValues.get(i);
+
+                Integer[] ids = {aval.getAttributeId()};
+
+                //FIXME remove auxDate workaround for date ranges
+                if (aval instanceof DateAttribute)
                 {
-                    /** Parser will only be != null if we are "searching" issues **/
-                    if (parser != null && aval instanceof DateAttribute)
+                    searchCriteriaExists = true;
+                    AttributeValue auxAval = aval.getChainedValue();
+
+                    Date date = parseDate(aval.getValue(), false); 
+                    Date auxDate = date;
+                    if(auxAval != null &&
+                       emptyString2null(auxAval.getValue()) != null)
                     {
-                        String auxDate = parser.getString("attv__" + aval.getAttributeId().intValue() + "val_aux");
-                        if (auxDate == null)
-                            auxDate = "";
-                        else
-                            auxDate = DateAttribute.internalDateFormat(auxDate.trim(), L10N.get(L10NKeySet.ShortDatePattern));
-                        aval.setValue(DateAttribute.internalDateFormat(aval.getValue(), L10N.get(L10NKeySet.ShortDatePattern)));
-                        searchCriteriaExists = true;
-                        Integer[] id = {aval.getAttributeId()};
-                        if (auxDate.equals(aval.getValue()))
-                            searchIndex.addQuery(id, aval.getValue());
-                        else
-                            searchIndex.addQuery(id, SearchIndex.TEXT + ":["+aval.getValue() + " TO " + auxDate + "]");
+                    	auxDate = parseDate(auxAval.getValue(), true);                        	
+                    }                        
+                    if (date.equals(auxDate))
+                    {    
+                    	searchIndex.addQuery(ids, DateAttribute.internalDateFormat(date));
                     }
-                    else if (aval instanceof StringAttribute)
+                    else
                     {
-                        searchCriteriaExists = true;
-                        Integer[] id = {aval.getAttributeId()};
-                        searchIndex
-                            .addQuery(id, aval.getValue());
+                        searchIndex.addQuery(ids, 
+                            SearchIndex.TEXT + ":["
+                            +DateAttribute.internalDateFormat(date) 
+                            + " TO " 
+                            + DateAttribute.internalDateFormat(auxDate) 
+                            + "]"
+                        );
                     }
                 }
-                
+                else if (aval instanceof StringAttribute)
+                {
+                    searchCriteriaExists = true;
+                    searchIndex.addQuery(ids, aval.getValue());
+                }
             }
         }
 
@@ -2000,7 +1108,7 @@
         {
             try 
             {
-                matchingIssueIds = searchIndex.getRelatedIssues(mergeTextResults);    
+                matchingIssueIds = searchIndex.getRelatedIssues(getMergePartialTextQueries());    
             }
             catch (Exception e)
             {
@@ -2010,791 +1118,594 @@
         }
 
         SearchFactory.releaseInstance(searchIndex);
+        
         return matchingIssueIds;
+    }
 
+    private static String useAlias(String alias, String tableColumn)
+    {
+        int dot = tableColumn.indexOf('.');
+        if(dot!=-1)
+        {
+            return alias + tableColumn.substring(dot);
+        }
+            else
+        {
+            return tableColumn;
+        }
+    }
+    
+    private void addMITCriteria(Criteria crit)
+        throws org.apache.torque.TorqueException
+    {   
+        mitList.addToCriteria(crit);
     }
 
-    private void addStateChangeQuery(StringBuffer from)
-        throws Exception
+    private void addMatchedTextCriteria(Criteria crit, Long[] issueIdsMatchedText)
     {
-        Integer oldOptionId = getStateChangeFromOptionId();
-        Integer newOptionId = getStateChangeToOptionId();
-        Date minUtilDate = parseDate(getStateChangeFromDate(), false);
-        Date maxUtilDate = parseDate(getStateChangeToDate(), true);
-        if ((oldOptionId != null &&  !oldOptionId.equals(NUMBERKEY_0))
-            || (newOptionId != null && !newOptionId.equals(NUMBERKEY_0))
-            || minUtilDate != null || maxUtilDate != null)
+        if(issueIdsMatchedText!=null)
         {
-            joinCounter++;
-            from.append(INNER_JOIN + ActivityPeer.TABLE_NAME + ON +
-                        ActivityPeer.ISSUE_ID + '=' + IssuePeer.ISSUE_ID);
+    	    crit.andIn(IssuePeer.ISSUE_ID, issueIdsMatchedText);
+        }
+    }
 
-            if (oldOptionId == null && newOptionId == null)
-            {
-                from.append(AND).append(ActivityPeer.ATTRIBUTE_ID)
-                    .append('=').append(getStateChangeAttributeId());
-            }
-            else
-            {
-                if (newOptionId != null && !newOptionId.equals(NUMBERKEY_0)) 
-                {
-                    from.append(AND).append(ActivityPeer.NEW_OPTION_ID)
-                        .append('=').append(newOptionId);
-                }
-                if (oldOptionId != null && !oldOptionId.equals(NUMBERKEY_0))
-                {
-                    from.append(AND).append(ActivityPeer.OLD_OPTION_ID)
-                        .append('=').append(oldOptionId);
-                }
-            }
-            from.append(')');
-
-            // add dates, if given
-            if (minUtilDate != null || maxUtilDate != null) 
-            {
-                joinCounter++;
-                from.append(INNER_JOIN + ActivitySetPeer.TABLE_NAME + ON +
-                             ActivitySetPeer.TRANSACTION_ID + '=' +
-                             ActivityPeer.TRANSACTION_ID);
-                from.append(AND);
-
-                addDateRange(ActivitySetPeer.CREATED_DATE, 
-                             minUtilDate, maxUtilDate, from);
-                
-                from.append(')');
-            }
-        }
-    }
-
-    private Long[] addCoreSearchCriteria(StringBuffer fromClause, 
-                                              StringBuffer whereClause,
-                                              Set tableAliases,
-                                              boolean mergePartialQueryResults)
-        throws Exception
+    private void addSortColumn(Criteria crit, String sortColumn)
     {
-        if (isXMITSearch()) 
+        crit.addSelectColumn(sortColumn);
+        
+        if(getSortPolarity().equals(ASC))
         {
-            Criteria crit = new Criteria();
-            mitList.addToCriteria(crit);
-            String sql = crit.toString();
-            int wherePos = sql.indexOf(" WHERE ");
-            String where = sql.substring(wherePos + 7);
-            whereClause.append(where);
+           crit.addAscendingOrderByColumn(sortColumn);
         }
-        else 
+        else
         {
-            whereClause.append(IssuePeer.MODULE_ID).append('=')
-                .append(getModule().getModuleId());
-            whereClause.append(AND).append(IssuePeer.TYPE_ID).append('=')
-                .append(getIssueType().getIssueTypeId());
+           crit.addDescendingOrderByColumn(sortColumn);
         }
-        whereClause.append(AND).append(IssuePeer.DELETED).append("=0");
-        whereClause.append(AND).append(IssuePeer.MOVED).append("=0");
+    }
 
-        // add option values
-        lastUsedAVList = new ArrayList(getAttributeValues());
+    private void setupSortColumn(Criteria crit, Integer sortAttrId)
+        throws TorqueException
+    {           
+        crit.addAlias(SORT_TABLE, AttributeValuePeer.TABLE_NAME);
 
-        // remove unset AttributeValues before searching
-        List setAttValues = removeUnsetValues(lastUsedAVList);        
-        addSelectedAttributes(fromClause, whereClause, setAttValues, tableAliases);
+        crit.addJoin(
+            IssuePeer.ISSUE_ID,
+            useAlias(SORT_TABLE, AttributeValuePeer.ISSUE_ID) 
+             + ( " AND "  
+             + useAlias(SORT_TABLE, AttributeValuePeer.DELETED) + " = 0 AND " +
+            useAlias(SORT_TABLE, AttributeValuePeer.ATTRIBUTE_ID) + " = " + sortAttrId
+            ).replace('.', DOT_REPLACEMENT_IN_JOIN_CONDITION ), 
+            Criteria.LEFT_JOIN
+        );
+        crit.addSelectColumn(useAlias(SORT_TABLE, AttributeValuePeer.VALUE_ID));
 
-        // search for issues based on text
-        Long[] matchingIssueIds = getTextMatches(setAttValues, mergePartialQueryResults);
+        String sortColumn;
+        Attribute att = AttributeManager.getInstance(sortAttrId); 
 
-        if (matchingIssueIds == null || matchingIssueIds.length > 0)
+        if (att.isOptionAttribute())
         {
-            addIssueIdRange(whereClause);
-            //addMinimumVotes(whereClause);
-
-            // add user values
-            addUserAndCreatedDateCriteria(fromClause, whereClause);
-
-            // add text search matches
-            addIssuePKsCriteria(whereClause, matchingIssueIds);
-
-            // state change query
-            addStateChangeQuery(fromClause);
+            crit.addJoin(
+                IssuePeer.MODULE_ID, 
+                RModuleOptionPeer.MODULE_ID
+                + ( " AND " 
+                +  IssuePeer.TYPE_ID + " = " + RModuleOptionPeer.ISSUE_TYPE_ID +
+                " AND " + RModuleOptionPeer.OPTION_ID + " = " + useAlias(SORT_TABLE, AttributeValuePeer.OPTION_ID)
+                ).replace('.', DOT_REPLACEMENT_IN_JOIN_CONDITION ), 
+                Criteria.LEFT_JOIN
+            );
+            sortColumn = RModuleOptionPeer.PREFERRED_ORDER;
         }
-        return matchingIssueIds;
-    }
-
-    private void addIssuePKsCriteria(StringBuffer sb, Long[] ids)
-    {
-       if (ids != null && ids.length > 0)
-       {
-           sb.append(AND).append(IssuePeer.ISSUE_ID).append(IN)
-               .append(StringUtils.join(ids, ",")).append(')');
-       }     
-    }
-
-    /**
-     * Get a List of Issues that match the criteria given by this
-     * SearchIssue's searchWords and the quick search attribute values.
-     * Perform a logical AND on partial queries (in text searches)
-     * @return a <code>List</code> value
-     * @exception Exception if an error occurs
-     */
-    public IteratorWithSize getQueryResults()
-        throws ComplexQueryException, Exception
-    {
-        return getQueryResults(false);
-    }
-
-    /**
-     * Get a List of Issues that match the criteria given by this
-     * SearchIssue's searchWords and the quick search attribute values.
-     * if (mergePartialQueries==true) perform a logical OR on partial queries,
-     * otherwise perform a logical AND on partial queries.
-     * @return a <code>List</code> value
-     * @exception Exception if an error occurs
-     */
-    public IteratorWithSize getQueryResults(boolean mergePartialQueries)
-        throws ComplexQueryException, Exception
-    {
-        checkModified();
-        if (!isSearchAllowed) 
+        else 
         {
-            lastQueryResults = IteratorWithSize.EMPTY;            
-        }
-        else if (lastQueryResults == null) 
-        {
-            Set tableAliases = new HashSet();
-            StringBuffer from = new StringBuffer();
-            StringBuffer where = new StringBuffer();
-            joinCounter = 0;
-            Long[] matchingIssueIds = addCoreSearchCriteria(from, where,
-                                                            tableAliases,
-                                                            mergePartialQueries);
-            if (joinCounter > MAX_INNER_JOIN) 
-            {
-                //WORK [HD} Need refactoring here. How can a user
-                //          create too complex queries ?
-                throw new ComplexQueryException(L10NKeySet.ExceptionQueryTooComplex);
-            }
-            // the matchingIssueIds are text search matches.  if length == 0,
-            // then no need to search further.  if null then there was no
-            // text to search, so continue the search process.
-            if (matchingIssueIds == null || matchingIssueIds.length > 0) 
-            {            
-                lastQueryResults = getQueryResults(from, where, tableAliases, mergePartialQueries);
-            }
-            else 
-            {
-                lastQueryResults = IteratorWithSize.EMPTY;
-            }            
+            sortColumn = useAlias(SORT_TABLE, AttributeValuePeer.VALUE);
         }
         
-        return lastQueryResults;
+        addSortColumn(crit, sortColumn);
     }
 
-    public int getIssueCount()
-    throws ComplexQueryException, Exception
+    private void setupInternalSortColumn(Criteria crit, String sortInternal)
     {
-        
-        return getIssueCount(false);
-    }
+        String sortColumn = null;
+        String joinColumn = null;
 
-    public int getIssueCount(boolean mergePartialQueries)
-        throws ComplexQueryException, Exception
-    {
-        checkModified();
-        int count = 0;
-        if (isSearchAllowed) 
+        if (sortInternal.equals(RModuleUserAttribute.MODULE.getName()))
         {
-            if (lastTotalIssueCount >= 0) 
-            {
-                count = lastTotalIssueCount;
-            }
-            else 
-            {
-                count = countFromDB(mergePartialQueries);
-            }
-            lastTotalIssueCount = count;
-        }
+            sortColumn = useAlias(SORT_TABLE, ScarabModulePeer.MODULE_NAME);
 
-        return count;
-    }
+            crit.addAlias(SORT_TABLE, ScarabModulePeer.TABLE_NAME);
+            crit.addJoin( 
+                IssuePeer.MODULE_ID, 
+                useAlias(SORT_TABLE, ScarabModulePeer.MODULE_ID), 
+                Criteria.LEFT_JOIN 
+            );
+        }
+        else if (sortInternal.equals(RModuleUserAttribute.ISSUE_TYPE.getName()))
+        {
+            sortColumn = useAlias(SORT_TABLE, IssueTypePeer.NAME);
 
-    private int countFromDB(boolean mergePartialQueries)
-        throws ComplexQueryException, Exception
-    {
-        int count = 0;
-        StringBuffer from = new StringBuffer();
-        StringBuffer where = new StringBuffer();
-        joinCounter = 0;
-        Long[] matchingIssueIds = addCoreSearchCriteria(from, where,
-                                                        new HashSet(),
-                                                        mergePartialQueries);
-        if (joinCounter > MAX_INNER_JOIN) 
-        {
-            //WORK [HD} Need refactoring here. How can a user
-            //          create too complex queries ?
-            //[JRG] The answer is: Putting values in too much attribute-lists,
-            //      because for every one, an inner join will be created.
-            //      So, new question; How much is *too* complex?
-            //      Should we get this limit highere?
-            //
-            throw new ComplexQueryException(L10NKeySet.ExceptionQueryTooComplex);
-        }
-        
-        if (matchingIssueIds == null || matchingIssueIds.length > 0) 
-        {
-            StringBuffer sql = new StringBuffer("SELECT count(DISTINCT ");
-            sql.append(IssuePeer.ISSUE_ID).append(')').append(" FROM ")
-                .append(IssuePeer.TABLE_NAME);
-            if (from.length() > 0) 
+            crit.addAlias(SORT_TABLE, IssueTypePeer.TABLE_NAME);
+            crit.addJoin( 
+                IssuePeer.TYPE_ID, 
+                useAlias(SORT_TABLE, IssueTypePeer.ISSUE_TYPE_ID), 
+                Criteria.LEFT_JOIN 
+            );
+        }
+        if (sortInternal.equals(RModuleUserAttribute.MODIFIED_DATE.getName()) ||
+            sortInternal.equals(RModuleUserAttribute.CREATED_DATE.getName()))
+        {
+            if (sortInternal.equals(RModuleUserAttribute.CREATED_DATE.getName()))
             {
-                sql.append(' ').append(from.toString());
+                joinColumn  = IssuePeer.CREATED_TRANS_ID;
             }
-            if (where.length() > 0) 
+            else
             {
-                sql.append(WHERE).append(where.toString());
+                joinColumn  = IssuePeer.LAST_TRANS_ID;
             }
-            String countSql = sql.toString();
-            
-            Connection localCon = conn;
-            Statement stmt = null;
-            try
+            sortColumn = useAlias(SORT_TABLE, ActivitySetPeer.CREATED_DATE);
+
+            crit.addAlias(SORT_TABLE, ActivitySetPeer.TABLE_NAME);
+            crit.addJoin( 
+                joinColumn, 
+                useAlias(SORT_TABLE,ActivitySetPeer.TRANSACTION_ID), 
+                Criteria.LEFT_JOIN 
+            );
+        }
+        else if (sortInternal.equals(RModuleUserAttribute.MODIFIED_BY.getName()) ||
+            sortInternal.equals(RModuleUserAttribute.CREATED_BY.getName()))
+        {   
+            if (sortInternal.equals(RModuleUserAttribute.CREATED_BY.getName()))
             {
-                if (localCon == null) 
-                {
-                    localCon = Torque.getConnection();
-                }
-                long startTime = System.currentTimeMillis();
-                stmt = localCon.createStatement();
-                ResultSet resultSet = stmt.executeQuery(countSql);
-                if (resultSet.next()) 
-                {
-                    count = resultSet.getInt(1);
-                }
-                logTime(countSql, System.currentTimeMillis() - startTime, 
-                        50L, 500L);
+                joinColumn  = IssuePeer.CREATED_TRANS_ID;
             }
-            finally
+            else
             {
-                if (stmt != null) 
-                {
-                    stmt.close();
-                }                
-                if (conn == null && localCon != null) 
-                {
-                    localCon.close();
-                }
+                joinColumn  = IssuePeer.LAST_TRANS_ID;
             }
+            sortColumn = useAlias(SORT_TABLE, ScarabUserImplPeer.LOGIN_NAME);
+
+            crit.addAlias(SORT_TABLE, ScarabUserImplPeer.TABLE_NAME);
+            crit.addAlias(SORT_HELP_TABLE, ActivitySetPeer.TABLE_NAME);
+            crit.addJoin( 
+                joinColumn, 
+                useAlias(SORT_HELP_TABLE, ActivitySetPeer.TRANSACTION_ID), 
+                Criteria.LEFT_JOIN 
+            );
+            crit.addJoin( 
+                useAlias(SORT_HELP_TABLE, ActivitySetPeer.CREATED_BY), 
+                useAlias(SORT_TABLE, ScarabUserImplPeer.USER_ID), 
+                Criteria.LEFT_JOIN 
+            );
         }
-        return count;
+
+        addSortColumn(crit, sortColumn);
     }
 
-    private static final String LOGGER = "org.apache.torque";
-    private void logTime(String message, long time, 
-                         long infoLimit, long warnLimit)
+    private void addSortCriteria(Criteria crit)
+        throws org.apache.torque.TorqueException
     {
-        if (time > warnLimit) 
+        Integer sortAttrId = getSortAttributeId();
+        String sortInternal = getSortInternalAttribute();
+        
+        if (sortAttrId != null) 
         {
-            Log.get(LOGGER).warn(message + "\nTime = " + time + " ms");
+            setupSortColumn(crit, sortAttrId);
         }
-        else if (time > infoLimit) 
+        else if (sortInternal != null)
         {
-            Logger log = Log.get(LOGGER);
-            if (log.isInfoEnabled()) 
-            {
-                log.info(message + "\nTime = " + time + " ms");                
-            }
+            setupInternalSortColumn(crit, sortInternal);
         }
         else
         {
-            Logger log = Log.get(LOGGER);
-            if (log.isDebugEnabled()) 
-            {
-                log.info(message + "\nTime = " + time + " ms");
-            }
-        }        
+        	addSortColumn(crit, IssuePeer.ISSUE_ID);
+        }
+        crit.addAscendingOrderByColumn(IssuePeer.ISSUE_ID);
     }
+    
+    private Criteria getCoreSearchCriteria(Long[] issueIdsMatchedText)
+        throws java.lang.Exception
+    {
+        Criteria crit = new Criteria();
 
-    private String setupSortColumn(Integer sortAttrId, 
-                                   StringBuffer sortOuterJoin,
-                                   Set tableAliases)
-        throws TorqueException
+        crit.addSelectColumn(IssuePeer.ISSUE_ID)
+            .and(IssuePeer.DELETED, false)
+            .and(IssuePeer.MOVED, false);
+
+        crit.setDistinct();
+
+        addMITCriteria(crit);
+        
+        addIssueIdRangeCriteria(crit);
+
+        addAttributeOptionCriteria(crit);
+
+        addMatchedTextCriteria(crit, issueIdsMatchedText);
+
+        addDateCriteria(crit);
+
+        addUserCriteria(crit);
+
+        addStateChangeCriteria(crit);
+
+        addSortCriteria(crit);
+        
+        return crit;
+    }
+
+    private void addStateChangeCriteria(Criteria crit)
+        throws Exception
     {
-        String alias = AV + sortAttrId;
-        if (!tableAliases.contains(alias)) 
+        Integer oldOptionId = getStateChangeFromOptionId();
+        Integer newOptionId = getStateChangeToOptionId();
+
+        if ((oldOptionId != null &&  !oldOptionId.equals(NUMBERKEY_0))
+            || (newOptionId != null && !newOptionId.equals(NUMBERKEY_0))
+            || getStateChangeFromDate() != null 
+            || getStateChangeToDate() != null)
         {
-            sortOuterJoin.append(LEFT_OUTER_JOIN)
-                .append(AttributeValuePeer.TABLE_NAME).append(' ')
-                .append(alias).append(ON)
-                .append(IssuePeer.ISSUE_ID).append('=')
-                .append(alias).append(".ISSUE_ID AND ").append(alias)
-                .append(".DELETED=0 AND ").append(alias)
-                .append(".ATTRIBUTE_ID=").append(sortAttrId).append(')');
-        }        
-            String sortColumn;
-            Attribute att = AttributeManager.getInstance(sortAttrId); 
-            if (att.isOptionAttribute())
-            {
-                // add the sort column
-                sortColumn = SORTRMO_PREFERRED_ORDER;
-                // join the RMO table to the alias we are sorting
-                sortOuterJoin.append(BASE_OPTION_SORT_LEFT_JOIN).append(alias)
-                    .append(DOT_OPTION_ID_PAREN);
+            crit.addAlias(STATE_CHANGE_TABLE, ActivityPeer.TABLE_NAME);
+            crit.addJoin( 
+                IssuePeer.ISSUE_ID, 
+                useAlias(STATE_CHANGE_TABLE,ActivityPeer.ISSUE_ID), 
+                Criteria.INNER_JOIN 
+            );
+
+            if (oldOptionId == null && newOptionId == null)
+            {
+                crit.and(useAlias(STATE_CHANGE_TABLE,ActivityPeer.ATTRIBUTE_ID), 
+                         getStateChangeAttributeId(),
+                         Criteria.EQUAL);
             }
-            else 
+            else
             {
-                sortColumn = alias + DOT_VALUE;
+                if (newOptionId != null && !newOptionId.equals(NUMBERKEY_0)) 
+                {
+                    crit.and(useAlias(STATE_CHANGE_TABLE,ActivityPeer.NEW_OPTION_ID), 
+                             newOptionId,
+                             Criteria.EQUAL);
+                }
+                if (oldOptionId != null && !oldOptionId.equals(NUMBERKEY_0))
+                {
+                    crit.and(useAlias(STATE_CHANGE_TABLE,ActivityPeer.OLD_OPTION_ID), 
+                             oldOptionId,
+                             Criteria.EQUAL);
+                }
+            }
+            if (getStateChangeFromDate() != null || getStateChangeToDate() != null)
+            {
+                crit.addAlias(STATE_CHANGE_DATE_TABLE, ActivitySetPeer.TABLE_NAME);
+
+                crit.addJoin( 
+                    useAlias(STATE_CHANGE_TABLE, ActivityPeer.TRANSACTION_ID), 
+                    useAlias(STATE_CHANGE_DATE_TABLE, ActivitySetPeer.TRANSACTION_ID), 
+                    Criteria.INNER_JOIN 
+                );
+               addDateRangeCriteria( crit, useAlias(STATE_CHANGE_DATE_TABLE, ActivitySetPeer.CREATED_DATE), 
+                                getStateChangeFromDate(), getStateChangeToDate());
             }
-            return sortColumn;
+        }
     }
 
-    private String setupInternalSortColumn(String sortInternal, StringBuffer sortOuterJoin, Set tableAliases)
-        throws TorqueException
-    {
-        String sortColumn = null;
-        String joinColumn = null;
-        String alias = ACTIVITYSETALIAS + "_sort";
-        if (sortInternal.equals(RModuleUserAttribute.MODIFIED_BY.getName()))
-        {
-               sortColumn = ACTSET_CREATED_BY;
-               joinColumn  = IssuePeer.LAST_TRANS_ID;
-        }
-        else if (sortInternal.equals(RModuleUserAttribute.MODIFIED_DATE.getName()))
+            
+            
+    private void addDateRangeCriteria( Criteria crit, String column, 
+                                  String minDateStr, String maxDateStr)
+        throws java.text.ParseException
+    {        
+        Date minDate = parseDate(minDateStr, false);
+        Date maxDate = parseDate(maxDateStr, true);
+    
+        if(minDate!=null)
         {
-            sortColumn = ACTSET_CREATED_DATE;
-            joinColumn  = IssuePeer.LAST_TRANS_ID;
+            crit.and(column, minDate, Criteria.GREATER_EQUAL);
         }
-        else if (sortInternal.equals(RModuleUserAttribute.CREATED_BY.getName()))
+        if(maxDate!=null)
         {
-            sortColumn = ACTSET_CREATED_BY;
-            joinColumn  = IssuePeer.CREATED_TRANS_ID;
+            crit.and(column, maxDate, Criteria.LESS_EQUAL);
         }
-        else if (sortInternal.equals(RModuleUserAttribute.CREATED_DATE.getName()))
+    }
+    
+    private void addTransDateRange(Criteria crit, 
+                                 String alias,
+                                 String baseColumn,
+                                 String minDateStr, String maxDateStr)
+        throws java.text.ParseException
+    {
+        if(minDateStr != null || maxDateStr != null)
         {
-            sortColumn = ACTSET_CREATED_DATE;
-            joinColumn  = IssuePeer.CREATED_TRANS_ID;
-        }
-        sortOuterJoin.append(LEFT_OUTER_JOIN)
-            .append(ActivitySetPeer.TABLE_NAME).append(' ')
-            .append(alias).append(ON)
-            .append(alias).append(".TRANSACTION_ID ")
-            .append('=').append(joinColumn).append(')');
-            
-        return alias + "." + sortColumn;
+            crit.addAlias(alias, ActivitySetPeer.TABLE_NAME);
+            crit.addJoin( 
+                baseColumn, 
+                useAlias(alias,ActivitySetPeer.TRANSACTION_ID), 
+                Criteria.INNER_JOIN 
+            );
+            addDateRangeCriteria(crit,useAlias(alias, ActivitySetPeer.CREATED_DATE),
+                                 minDateStr,maxDateStr);    
+        } 
     }
+    
+    private void addDateCriteria(Criteria crit)
+        throws Exception
+    {        
+        addTransDateRange(crit, "CHANGE_DATE_TABLE", IssuePeer.LAST_TRANS_ID,
+                          getMinChangeDate(), getMaxChangeDate());
+        addTransDateRange(crit, "CREATE_DATE_TABLE", IssuePeer.CREATED_TRANS_ID,
+                          getMinCreationDate(), getMinCreationDate());
+    }
+        
+    private void addUserCriteria(Criteria crit)
+        throws Exception
+    {        
+        List anyUsers = new ArrayList();
+        List creatorUsers = new ArrayList();
+        Map attrUsers = new HashMap();
 
-    private List getSearchSqlPieces(StringBuffer from, StringBuffer where,
-                                    Set tableAliases)
-        throws TorqueException
-    {
-        List searchStuff = new ArrayList(3);
-        Integer sortAttrId = getSortAttributeId();
-        String sortInternal = getSortInternalAttribute();
+        for (Iterator i = searchUsers.entrySet().iterator(); i.hasNext();)
+        {                
+            Map.Entry entry = (Map.Entry)i.next();
+            String userId = (String)entry.getKey();
+            Set attrIds = (Set)entry.getValue();
 
-        // Get matching issues, with sort criteria
-        StringBuffer sql = getSelectStart();
-        // WARNING!! The order of this fields is important!!
-        // SEE: doPrepareNextQueryResult in this class!!
-        sql.append(',').append(IssuePeer.MODULE_ID)
-            .append(',').append(IssuePeer.TYPE_ID)
-            .append(',').append(ACTIVITYSETALIAS).append('.').append(ACTSET_CREATED_BY)
-            .append(',').append(ACTIVITYSETALIAS).append('.').append(ACTSET_CREATED_DATE)
-            .append(',').append(ACTIVITYSETALIAS_MODIFICATION).append('.').append(ACTSET_MODIFIED_BY)
-            .append(',').append(ACTIVITYSETALIAS_MODIFICATION).append('.').append(ACTSET_MODIFIED_DATE);
-        String sortColumn = null;
-        StringBuffer sortOuterJoin = null;
-        if (sortAttrId != null) 
-        {
-            sortOuterJoin = new StringBuffer(128);
-            sortColumn = setupSortColumn(sortAttrId, sortOuterJoin,
-                                         tableAliases);
-            sql.append(',').append(sortColumn);
+            for ( Iterator i2 = attrIds.iterator(); i2.hasNext();)
+            {
+                String attrId = (String)i2.next();
+
+    	        if(SEARCHING_USER_KEY.equalsIgnoreCase(userId))
+    	        {
+    	            userId=searchingUser.getUserId().toString();
+    	        }
+            
+    	        if(ANY_KEY.equals(attrId))
+    	        {
+    	        	anyUsers.add(userId);
+    	        }
+    	        else if (CREATED_BY_KEY.equals(attrId)) 
+    	        {
+    	            creatorUsers.add(userId);
+    	        }
+    	        else 
+    	        {
+    	            List userIds = (List)attrUsers.get(attrId);
+    	            if (userIds == null) 
+    	            {
+    	                userIds = new ArrayList();
+    	                attrUsers.put(attrId, userIds);
+    	            }
+    	            userIds.add(userId);
+    	        }
+
+            }
         }
-        else if (sortInternal != null)
+
+        if (anyUsers.size()>0 || attrUsers.size()>0 || creatorUsers.size()>0)
+        {
+            crit.addAlias("USER_TABLE", ActivityPeer.TABLE_NAME);
+            crit.addJoin( 
+                IssuePeer.ISSUE_ID, 
+                useAlias("USER_TABLE",ActivityPeer.ISSUE_ID), 
+                Criteria.INNER_JOIN 
+            );
+        }                
+
+        if (anyUsers.size()>0)
         {
-            sortOuterJoin = new StringBuffer(128);
-            sortColumn = setupInternalSortColumn(sortInternal, sortOuterJoin,
-                                            tableAliases);
-            sql.append(',').append(sortColumn);
-        }
-
-        sql.append(FROM).append(IssuePeer.TABLE_NAME);
-
-        // add the join clause if not already exists
-        String joinAliasPart = ' '+ACTIVITYSETALIAS+ON; 
-        if (from.lastIndexOf(joinAliasPart)==-1) 
-    	{ 
-	        sql.append(INNER_JOIN).append(ActivitySetPeer.TABLE_NAME);
-	        sql.append(joinAliasPart);
-	        sql.append(IssuePeer.CREATED_TRANS_ID).append('=');
-	        sql.append(ACTIVITYSETALIAS).append('.').append(ACTSET_TRAN_ID).append(')');
-    	}
-        
-        // add the join clause if not already exists
-        joinAliasPart = ' '+ACTIVITYSETALIAS_MODIFICATION+ON;
-    	if (from.lastIndexOf(joinAliasPart)==-1) 
-    	{ 
-	        sql.append(LEFT_OUTER_JOIN).append(ActivitySetPeer.TABLE_NAME);
-	        sql.append(joinAliasPart);
-	        sql.append(IssuePeer.LAST_TRANS_ID).append('=');
-	        sql.append(ACTIVITYSETALIAS_MODIFICATION).append('.').append(ACTSET_TRAN_ID).append(')');
-    	}
-
-        if (from.length() > 0) 
-        {
-            sql.append(' ').append(from.toString());
-        }
-        if (sortOuterJoin != null) 
-        {
-            sql.append(sortOuterJoin);    
-        }
-        if (where.length() > 0) 
-        {
-            sql.append(WHERE).append(where.toString());
-        }
-        addOrderByClause(sql, sortColumn);
-        searchStuff.add(sql.toString());
-
-        // add the attribute value columns that will be shown in the list.
-        // these are joined using a left outer join, so the additional
-        // columns do not affect the results of the search (no additional
-        // criteria are added to the where clause.)          
-        List rmuas = getIssueListAttributeColumns();
-        if (rmuas != null)
-        {
-            int valueListSize = rmuas.size();
-            StringBuffer outerJoin = new StringBuffer(10 * valueListSize + 20);
-
-            int count = 0;
-            int maxJoin = MAX_JOIN - 2;
-            //List columnSqlList = new ArrayList(valueListSize/maxJoin + 1);
-            StringBuffer partialSql = getSelectStart();
-            tableAliases = new HashSet(MAX_JOIN);
-            for (Iterator i = rmuas.iterator(); i.hasNext();) 
-            {
-                RModuleUserAttribute rmua = (RModuleUserAttribute)i.next();
-                Integer attrPK = rmua.getAttributeId();
-          
+            crit.addIn(useAlias("USER_TABLE",ActivityPeer.NEW_USER_ID), anyUsers);
+        }                                     
+        if (attrUsers.size()>0) 
+        {
+            for (Iterator i = attrUsers.entrySet().iterator(); i.hasNext();)
+            {                
+                Map.Entry entry = (Map.Entry)i.next();
+                String attrId = (String)entry.getKey();
+                List userIds = (List)entry.getValue();
                 
-                String id = attrPK.toString();
-                String alias = AV + id;
-                // add column to SELECT column clause
-                partialSql.append(',').append(alias).append(DOT_VALUE);
-                // if no criteria was specified for a displayed attribute
-                // add it as an outer join
-                if (!tableAliases.contains(alias) 
-                    && !attrPK.equals(sortAttrId))
+                Criteria.Criterion userIds4attrId = crit.getNewCriterion(
+                    useAlias("USER_TABLE",ActivityPeer.NEW_USER_ID),
+                    userIds,
+                    Criteria.IN
+                );
+                userIds4attrId.and(crit.getNewCriterion(
+                    useAlias("USER_TABLE",ActivityPeer.ATTRIBUTE_ID),
+                    attrId,
+                    Criteria.EQUAL
+                ));
+                
+                Criteria.Criterion c = crit.getCriterion(useAlias("USER_TABLE",ActivityPeer.NEW_USER_ID));
+                if(c!=null)
                 {
-                    outerJoin.append(LEFT_OUTER_JOIN)
-                        .append(AttributeValuePeer.TABLE_NAME).append(' ')
-                        .append(alias).append(ON)
-                        .append(IssuePeer.ISSUE_ID).append('=')
-                        .append(alias).append(".ISSUE_ID AND ").append(alias)
-                        .append(".DELETED=0 AND ").append(alias)
-                        .append(".ATTRIBUTE_ID=").append(id).append(')');
-                    tableAliases.add(alias);
+                	c.or(userIds4attrId);
                 }
-
-                count++;
-                if (count == maxJoin || !i.hasNext()) 
+                else
                 {
-                    ColumnBundle cb = new ColumnBundle();
-                    cb.size = count;
-                    if (sortAttrId != null) 
-                    {
-                        cb.sortColumn = setupSortColumn(sortAttrId, outerJoin, tableAliases);
-                        partialSql.append(',').append(cb.sortColumn);
-                    }
-                    else if (sortInternal != null)
-                    {
-                        cb.sortColumn = setupInternalSortColumn(sortInternal, outerJoin, tableAliases);
-                        partialSql.append(',').append(cb.sortColumn);
-                    }
-                    cb.select = partialSql;
-                    cb.outerJoins = outerJoin;
-                    searchStuff.add(cb);
-
-                    partialSql = getSelectStart();
-                    outerJoin = new StringBuffer(512);
-                    tableAliases.clear();
-                    count = 0;
+                	crit.add(userIds4attrId);
                 }
             }
         }
-        return searchStuff;
-    }
-
-    private IteratorWithSize getQueryResults(StringBuffer from, 
-                                             StringBuffer where,
-                                             Set tableAliases,
-                                             boolean mergePartialQueries)
-        throws TorqueException, ComplexQueryException, Exception
-    {
-        // return a List of QueryResult objects
-        IteratorWithSize result = null;
-        try
+        if (anyUsers.size()>0 || creatorUsers.size()>0)
         {
-            if (conn == null)
-            {
-                conn = Torque.getConnection();
-                connectionStartTime = System.currentTimeMillis();
-            }
+            List anyAndCreators = new ArrayList();
+            anyAndCreators.addAll(anyUsers);
+            anyAndCreators.addAll(creatorUsers);
+
+            crit.addAlias("CREATOR_USER_TABLE", ActivitySetPeer.TABLE_NAME);
+            crit.addJoin( 
+                IssuePeer.CREATED_TRANS_ID, 
+                useAlias("CREATOR_USER_TABLE",ActivitySetPeer.TRANSACTION_ID), 
+                Criteria.INNER_JOIN 
+            );
 
-            // The code currently always calls getIssueCount() after we run this
-            // query.  We can avoid having to use 2 connections by calling it
-            // now using 'conn'.  It leaves the possibility of running the two
-            // queries within a transaction as well.  We also use the result 
-            // here to avoid the more complex query if there are no results.
-            int count = getIssueCount(mergePartialQueries);
-            if (count > 0) 
+            Criteria.Criterion userIds4anyAndCreators = crit.getNewCriterion(
+                useAlias("CREATOR_USER_TABLE",ActivitySetPeer.CREATED_BY),
+                anyAndCreators,
+                Criteria.IN
+            );
+
+            Criteria.Criterion c = crit.getCriterion(useAlias("USER_TABLE",ActivityPeer.NEW_USER_ID));
+            if(c!=null)
             {
-                result = new QueryResultIterator(this, count, from, where,
-                                                 tableAliases);
+            	c.or(userIds4anyAndCreators);
             }
-            else 
+            else
             {
-                result = IteratorWithSize.EMPTY;
+            	crit.add(userIds4anyAndCreators);
             }
         }
-        catch (SQLException e)
-        {
-            close();
-            throw e; //EXCEPTION
-        }
-        /*
-        catch (TorqueException e)
-        {
-            close();
-            throw e;
-        }
-        */
-        return result;
     }
-
-    private void addOrderByClause(StringBuffer sql, String sortColumn)
+        
+    private void addIssueIdRangeCriteria(Criteria crit)
+        throws java.lang.Exception
     {
-        if (sortColumn == null) 
+        Issue.FederatedId minFid = null;
+        Issue.FederatedId maxFid = null;
+
+        if(minId != null)
         {
-            sql.append(ORDER_BY).append(IssuePeer.ID_PREFIX);
-            sql.append(' ').append(getSortPolarity());
-            sql.append(',').append(IssuePeer.ID_COUNT);
-            sql.append(' ').append(getSortPolarity());
+            minFid = new Issue.FederatedId(minId);
         }
-        else 
+        if(maxId != null)
         {
-            sql.append(ORDER_BY).append(sortColumn);
-            sql.append(' ').append(getSortPolarity());
-            // add pk sort so that rows can be combined easily
-            sql.append(',').append(IssuePeer.ISSUE_ID).append(" ASC");
+            maxFid = new Issue.FederatedId(maxId);
         }
-    }
+        setDefaults(minFid, maxFid);
 
-    private StringBuffer getSelectStart()
-    {
-        StringBuffer sql = new StringBuffer(512);
-        sql.append(SELECT_DISTINCT)
-            .append(IssuePeer.ISSUE_ID).append(',')
-            .append(IssuePeer.ID_PREFIX).append(',')
-            .append(IssuePeer.ID_COUNT);
-        return sql;
-    }
-
-
-    /**
-     * Used by QueryResult to avoid multiple db hits in the event caching
-     * is not being used application-wide.  It is used if the IssueList.vm
-     * template is printing the module names next to each issue id.
-     * As this IssueSearch object is short-lived, use of a simple Map based
-     * cache is ok, need to re-examine if the lifespan is increased.
-     *
-     * @param id an <code>Integer</code> value
-     * @return a <code>Module</code> value
-     * @exception TorqueException if an error occurs
-     */
-    Module getModule(Integer id)
-        throws TorqueException
-    {
-        Module module = (Module)moduleMap.get(id);
-        if (module == null)
+        if ( minFid != null
+          && maxFid != null
+          && (   minFid.getCount() > maxFid.getCount() 
+              || !StringUtils.equals(minFid.getPrefix(), maxFid.getPrefix())
+              || !StringUtils.equals(minFid.getDomain(), maxFid.getDomain())))
         {
-            module = ModuleManager.getInstance(id);
-            moduleMap.put(id, module);
+            throw new ScarabException(L10NKeySet.ExceptionIncompatibleIssueIds, minId, maxId);
         }
-        return module;
-    }
-    
-    /**
-     * Used by QueryResult to avoid multiple db hits in the event caching
-     * is not being used application-wide.  It is used if the IssueList.vm
-     * template is printing the issue type names next to each issue id.
-     * As this IssueSearch object is short-lived, use of a simple Map based
-     * cache is ok, need to re-examine if the lifespan is increased.
-     *
-     * @param moduleId an <code>Integer</code> value
-     * @param issueTypeId an <code>Integer</code> value
-     * @return a <code>RModuleIssueType</code> value
-     * @exception TorqueException if an error occurs
-     */
-    RModuleIssueType getRModuleIssueType(Integer moduleId, Integer issueTypeId)
-        throws TorqueException
-    {
-        SimpleKey[] nks = {SimpleKey.keyFor(moduleId.intValue()), 
-                           SimpleKey.keyFor(issueTypeId.intValue())};
-        ObjectKey key = new ComboKey(nks);
-        RModuleIssueType rmit = (RModuleIssueType)rmitMap.get(key);
-        if (rmit == null)
+        else 
         {
-            rmit = RModuleIssueTypeManager.getInstance(key);
-            rmitMap.put(key, rmit);
-        }
-        return rmit;
+            addIssueIdCrit(crit, minFid, Criteria.GREATER_EQUAL );
+            addIssueIdCrit(crit, maxFid, Criteria.LESS_EQUAL );
+        }        
     }
-
-    /**
-     * Called by the garbage collector to release any database
-     * resources associated with this query.
-     *
-     * @see #close()
-     */
-    protected void finalize()
-        throws Throwable
+        
+    private void addIssueIdCrit(Criteria crit, Issue.FederatedId fId, SqlEnum comparisionType)
     {
-        try
-        {
-            if (conn != null) 
-            {
-                Log.get(LOGGER)
-                    .warn("Closing connection in " + this + " finalizer");
-                // if this object was left this state it is very likely that
-                // the IssueSearchFactory was not notified either.
-                // We error on the side of possibly increasing the available
-                // IssueSearch objects, over potentially freezing users out
-                IssueSearchFactory.INSTANCE.notifyDone();
-            }
-        }
-        finally
+        if (fId != null)
         {
-            close();
-            super.finalize();
+            crit.and(IssuePeer.ID_COUNT, fId.getCount(), comparisionType)
+                .and(IssuePeer.ID_DOMAIN, fId.getDomain())
+                .and(IssuePeer.ID_PREFIX, fId.getPrefix());
         }
     }
 
-    /**
-     * Releases any managed resources associated with this search
-     * (e.g. database connections, etc.).
-     */
-    public void close()
+    private void addAttributeOptionCriteria(Criteria crit)
+        throws java.lang.Exception
     {
-        if (conn != null)
+        List setAttValues = getSetAttributeValues();
+
+        Map attrMap = new HashMap((int)(setAttValues.size()*1.25));
+        for (int j=0; j<setAttValues.size(); j++) 
         {
-            // Be extremely paranoid about assuring that the database
-            // connection is released to avoid leaks.
-            try
-            {
-                Logger log = Log.get(LOGGER);
-                if (log.isDebugEnabled())
-                {
-                    log.debug("Releasing issue search database connection");
-                }
-            }
-            finally
-            {
-                try 
-                {
-                    if (searchRS != null) 
-                    {
-                        searchRS.close();
-                        searchRS = null;
-                    }
-                }
-                catch (Exception e)
-                {
-                    try
-                    {
-                        Log.get(LOGGER).warn(
-                            "Unable to close jdbc Statement", e);
-                    }
-                    catch (Exception ignore)
-                    {
-                    }
-                }
-                try 
+            AttributeValue multiAV = (AttributeValue)setAttValues.get(j);
+            if (multiAV instanceof OptionAttribute)
+            {                
+                //pull any chained values out to create a flat list
+                List flatOptions = new ArrayList();
+                List chainedValues = multiAV.getValueList();
+                for (int i=0; i<chainedValues.size(); i++) 
                 {
-                    if (searchStmt != null) 
+                    AttributeValue aval = (AttributeValue)chainedValues.get(i);
+                    Integer optionId = aval.getOptionId();
+                    if(optionId == null)
                     {
-                        searchStmt.close();
-                        searchStmt = null;
+                        continue;
                     }
-                }
-                catch (Exception e)
-                {
-                    try
+                    if (optionId.intValue() != 0) // Empty value is 0
                     {
-                        Log.get(LOGGER).warn(
-                            "Unable to close jdbc Statement", e);
+                        buildOptionList(flatOptions, aval);
                     }
-                    catch (Exception ignore)
+                    else
                     {
+                        flatOptions.add(optionId);
                     }
                 }
 
-                try 
-                {
-                    closeStatementsAndResultSets();
-                    stmtList = null;
-                    rsList = null;
-                }
-                catch (Exception e)
-                {
-                    try
-                    {
-                        Log.get(LOGGER).warn(
-                            "Unable to close jdbc Statement", e);
-                    }
-                    catch (Exception ignore)
-                    {
-                    }
-                }
-                
-                Torque.closeConnection(this.conn);
-                this.conn = null;
-                logTime(this + 
-                        " released database connection which was held for:",
-                        System.currentTimeMillis() - connectionStartTime, 
-                        5000L, 30000L);
+                Integer attributeId = multiAV.getAttributeId();
+                attrMap.put(attributeId, flatOptions);
+            }
+        }
+
+        for (Iterator i=attrMap.entrySet().iterator(); i.hasNext();) 
+        {
+            Map.Entry options4Attribute = (Map.Entry)i.next();
+            List options = (List) options4Attribute.getValue();
+            Integer attributeId = (Integer) options4Attribute.getKey();
+            String alias = "av" + attributeId;
+                        
+            crit.addAlias(alias, AttributeValuePeer.TABLE_NAME);
+            crit.addJoin(
+                   IssuePeer.ISSUE_ID, 
+                   useAlias(alias, AttributeValuePeer.ISSUE_ID), 
+                   Criteria.INNER_JOIN
+                )
+                .and(useAlias(alias, AttributeValuePeer.DELETED), false)
+                .and(useAlias(alias, AttributeValuePeer.ATTRIBUTE_ID), attributeId)
+                .andIn(useAlias(alias, AttributeValuePeer.OPTION_ID), options );
+
+            if (options.contains(NUMBERKEY_0)) //is 'empty' option selected?
+            {                
+                crit.or(useAlias(alias, AttributeValuePeer.OPTION_ID), Criteria.ISNULL);
             }
         }
     }
 
-    
-    private void closeStatementsAndResultSets()
-        throws SQLException
+    /**
+     * Get a List of Issues that match the criteria given by this
+     * SearchIssue's searchWords and the quick search attribute values.
+     * Perform a logical AND on partial queries (in text searches)
+     * @return a <code>List</code> value
+     * @exception Exception if an error occurs
+     */
+    public List getQueryResults()
+        throws Exception
     {
-        if (rsList != null) 
+    	List queryResults = Collections.EMPTY_LIST;            
+        Criteria c = getSearchCriteria();
+        if(c!=null)
         {
-            for (Iterator iter = rsList.iterator(); iter.hasNext();) 
-            {
-                ((ResultSetAndSize)iter.next()).resultSet.close();
-            }
-            rsList.clear();            
+            queryResults = getQueryResults(c);
         }
-        
-        if (stmtList != null) 
+        return queryResults;
+    }
+
+    public int getIssueCount()
+        throws Exception
+    {
+        int count = 0;
+        Criteria c = getSearchCriteria();
+        if(c!=null)
         {
-            for (Iterator iter = stmtList.iterator(); iter.hasNext();) 
-            {
-                ((Statement)iter.next()).close();
-            }
-            stmtList.clear();            
+            count = (new CachedQuery(c, true)).getRowCount();
         }
+        return count;
     }
     
-    /**
-     * The query currently being launched, so we can access any value from it.
-     * @param query
-     */
-    public void setQuery(String query) throws Exception
+    private Criteria getSearchCriteria()
+        throws Exception
     {
-        this.parser = new StringValueParser();
-        parser.parse(query, '&', '=', true);        
+        Criteria c = null;
+    	if (isSearchAllowed) 
+        {
+            Long[] issueIdsMatchedText = getTextMatches();
+            
+            if (issueIdsMatchedText==null || issueIdsMatchedText.length > 0) 
+            {            
+            	c = getCoreSearchCriteria(issueIdsMatchedText);
+            }
+        }
+        return c;
     }
-    
+
+    private List getQueryResults(Criteria c)
+        throws Exception
+    {
+        return new QueryResultList(new CachedQuery(c, false));
+    }
+
     /**
      * Allows setting the L10N tool for using when is needed to know
      * the user's locale (example, when parsing date parameters) 
@@ -2804,350 +1715,105 @@
     {
         this.L10N = l10nTool;
     }
-
-    private class QueryResultIterator implements IteratorWithSize
+   
+    public void addAttributeValue(Attribute attribute, String value)
+    	throws TorqueException
     {
-        final IssueSearch search;
-        final List searchStuff;
-        final int size;
-
-        QueryResult[]  cachedQRs;
-
-        /**
-         * @param issues The issue query results.
-         */
-        private QueryResultIterator(IssueSearch search, int size, 
-                                    StringBuffer from, StringBuffer where,
-                                    Set tableAliases)
-            throws SQLException, TorqueException
-        {
-            this.search = search;
-            this.size = size;
-            searchStuff = getSearchSqlPieces(from, where, tableAliases);
-
-            int numQueries = searchStuff.size();
-            stmtList = new ArrayList(numQueries);
-            rsList = new ArrayList(numQueries);
-            
-            long queryStartTime = System.currentTimeMillis();
-            searchStmt = conn.createStatement();
-            String searchSql = (String)searchStuff.get(0);
-            try 
-            {
-                searchRS = searchStmt.executeQuery(searchSql);                
-                logTime(searchSql + 
-                    "\nTime to only execute the query, not return results.",
-                    System.currentTimeMillis() - queryStartTime, 
-                    50L, 500L);
-            }
-            catch (SQLException e)
-            {
-                Log.get(LOGGER).warn("Search sql:\n" + searchSql + 
-                    "\nresulted in an exception: " + e.getMessage());
-                throw e; //EXCEPTION
-                
-            }
-        }
+        AttributeValue av = AttributeValue.getNewInstance(attribute,searchIssue);
+        av.setValue(value);
+        searchIssue.addAttributeValue(av);
+    }
 
-        public int size()
-        {
-            return size;
-        }
+    public AttributeValue addAttributeValue(Attribute attribute, AttributeOption option)
+        throws TorqueException
+    {
+        AttributeValue av = AttributeValue.getNewInstance(attribute, searchIssue);
+        av.setAttributeOption(option);
+        searchIssue.addAttributeValue(av);
+        return av;
+    }
+    
+    public Module getModule()
+    {
+	    return singleModule;
+    }
 
-        // ----------------------------------------------------------------
-        // Iterator implementation
+    public IssueType getIssueType()
+    {
+	    return singleIssueType;
+    }
 
-        private QueryResult nextQueryResult;
-        public Object next()
-        {
-            if (hasNext()) 
-            {
-                hasNext = null;
-                return nextQueryResult;
-            }
-            else 
-            {
-                throw new NoSuchElementException("Iterator is exhausted"); //EXCEPTION
-            }
-        }
+    public List getAttributeValues()
+        throws TorqueException
+    {
+    	return searchIssue.getAttributeValues();
+    }
 
+    public void setQueryKey(String key)
+        throws Exception
+    {
+    }
 
-        private Boolean hasNext;
-        public boolean hasNext()
-        {
-            if (hasNext == null) 
-            {
-                hasNext = (prepareNextQueryResult()) 
-                    ? Boolean.TRUE : Boolean.FALSE;
-            }
-            return hasNext.booleanValue();
-        }
+    public String getQueryKey()
+    {
+    	return "";
+    }
+    
+    public void setMergePartialTextQueries(boolean mergePartialTextQueries)
+    {
+		this.mergePartialTextQueries = mergePartialTextQueries;
+	}
 
+    public boolean getMergePartialTextQueries()
+    {
+		return mergePartialTextQueries;
+	}
 
-        public void remove()
-        {
-            throw new UnsupportedOperationException(
-                "'remove' is not implemented"); //EXCEPTION
+	/**
+	 * @return
+	 * @throws TorqueException
+	 */
+	public List getSetAttributeValues() throws TorqueException {
+		return removeUnsetValues(searchIssue.getAttributeValues());
+	}
+    
+    private class QueryResultList extends AbstractList
+    {
+        private final CachedResultList queryResult;
+        
+        private QueryResultList(CachedQuery query)
+        {            
+            this.queryResult = (CachedResultList)query.getResults();
         }
 
-
-        int index = -1;
-        /**
-         * nextQueryResult should be non-null at the end of this method
-         * if it returns true, otherwise false should be returned.
-         *
-         * @return a <code>boolean</code> value
-         */
-        private boolean prepareNextQueryResult()
-        {
-            boolean anyMoreResults;
-            try 
-            {
-                anyMoreResults = doPrepareNextQueryResult();
-            }
-            catch (Exception e)
-            {
-                anyMoreResults = false;
-                Log.get(LOGGER).warn(
-                    "An exception prevented getting the next result.", e);
-            }
-            return anyMoreResults;
-        }            
-
-        private boolean doPrepareNextQueryResult()
-            throws SQLException
+        public int size()
         {
-            boolean anyMoreResults = true;
-            
-            if (index < 0 || index >= 1000)
-            {
-                if (cachedQRs == null) 
-                {
-                    cachedQRs = new QueryResult[1000];
-                }
-                else 
-                {
-                    // remove the old
-                    for (int i = cachedQRs.length - 1; i >= 0; i--) 
-                    {
-                        cachedQRs[i] = null;
-                    }
-                    closeStatementsAndResultSets();
-                }
-                
-                int count = 0;
-                QueryResult qr;
-                String previousPK = null;
-                StringBuffer pks = new StringBuffer(512);
-                while (count < 1000 && searchRS.next()) 
-                {
-                    String pk = searchRS.getString(1);
-                    if (!pk.equals(previousPK)) 
-                    {
-                        previousPK = pk;
-                        pks.append(pk).append(',');
-                        qr = new QueryResult(search);
-                        qr.setIssueId(pk);
-                        qr.setIdPrefix(searchRS.getString(2));
-                        qr.setIdCount(searchRS.getString(3));
-                        qr.setModuleId(new Integer(searchRS.getInt(4)));
-                        qr.setIssueTypeId(new Integer(searchRS.getInt(5)));
-                        qr.setCreatedBy(new Integer(searchRS.getInt(6)));
-                        qr.setCreatedDate(searchRS.getTimestamp(7));
-                        qr.setModifiedBy(new Integer(searchRS.getInt(8)));
-                        qr.setModifiedDate(searchRS.getTimestamp(9));
-                        cachedQRs[count++] = qr;
-                    }                    
-                }                
-
-                anyMoreResults = count > 0;
-                if (anyMoreResults) 
-                {
-                    index = 0;
-                    pks.setLength(pks.length() - 1);
-
-                    // execute column result queries
-                    if (searchStuff.size() > 1) 
-                    {
-                        Iterator i = searchStuff.iterator();
-                        i.next();
-                        while (i.hasNext()) 
-                        {
-                            ColumnBundle cb = (ColumnBundle)i.next();
-                            StringBuffer sql = new StringBuffer(512);
-                            sql.append(cb.select);
-
-                            sql.append(FROM).append(IssuePeer.TABLE_NAME);
-                            if (cb.outerJoins != null) 
-                            {
-                                sql.append(cb.outerJoins);    
-                            }
-                            sql.append(WHERE).append(IssuePeer.ISSUE_ID)
-                                .append(IN).append(pks).append(')');
-                            addOrderByClause(sql, cb.sortColumn);
-                            Statement stmt = conn.createStatement();
-                            ResultSet rs = stmt.executeQuery(sql.toString());
-                            rs.next();
-                            stmtList.add(stmt);
-                            rsList.add(new ResultSetAndSize(rs, cb.size));
-                        }
-                    }
-                }
-            }
-            else if (cachedQRs[index] == null)
-            {
-                anyMoreResults = false;                
-            }
-
-            if (anyMoreResults) 
-            {
-                // remove old results to allow gc, if needed
-                if (index > 0) 
-                {
-                    cachedQRs[index-1] = null;
-                }
-                nextQueryResult = cachedQRs[index++];
-                buildQueryResult(nextQueryResult);            
-            }
-
-            return anyMoreResults;
+            return queryResult.size();
         }
-
-
-        /**
-         * Assembles one or more rows from a <code>ResultSet</code> into a
-         * single {@link QueryResult} object.  Assumes that rows in the
-         * <code>ResultSet</code> are grouped by issue.
-         *
-         * @return A single {@link QueryResult} object.
-         * @exception SQLException If a database error occurs.
-         */
-        private void buildQueryResult(QueryResult qr)
-            throws SQLException
+        
+        public Object get(int index)
         {
-            String queryResultPK = qr.getIssueId();
-            Logger scarabLog = Log.get("org.tigris.scarab");
+            Record next = (Record) queryResult.get(index);
 
-            // add column values
-            int index = 0;
-            for (Iterator iter = rsList.iterator(); iter.hasNext();) 
+            try
             {
-                ResultSetAndSize rss = (ResultSetAndSize)iter.next();
-                ResultSet resultSet = rss.resultSet;
-                int size = rss.size;
-                String pk = resultSet.getString(1);
-                while (queryResultPK.equals(pk))
-                {
-                    List values = qr.getAttributeValues();
-                    // Each attribute can result in a separate record.  As we
-                    // have sorted on the primary key column in addition to
-                    // any other sort, all attributes for a given issue will
-                    // be grouped.  Map these multiple records into a single
-                    // QueryResult per issue.
-                    if (values == null || index >= values.size()) 
-                    {
-                        queryResultStarted(resultSet, qr, size);
-                        if (scarabLog.isDebugEnabled())
-                        {
-                            scarabLog.debug("Fetching query result at index "
-                                            + index + " with ID of "
-                                            + queryResultPK);
-                        }
-                    }
-                    else 
-                    {
-                        queryResultContinued(resultSet, qr, index, size);
-                    }
-                    
-                    pk = (resultSet.next()) ? resultSet.getString(1): null;
-                }
-                index += size;
+	            Long issueId = new Long(next.getValue(1).asString());
+	            Integer sortAttrId = getSortAttributeId();
+	            Long sortValueId = null;
+	            if(sortAttrId != null)
+	            { 
+	                String s = next.getValue(2).asString();
+	                if(s!=null)
+	                {
+	                    sortValueId = new Long(s);	 
+	                }                	 
+	            }
+	            return new QueryResult(issueId, issueListAttributeColumns, sortAttrId, sortValueId, L10N );
             }
-            qr.populateInternalAttributes(issueListAttributeColumns, L10N);
-        }
-
-        private void queryResultStarted(ResultSet rs, QueryResult qr, 
-                                        int valueListSize)
-            throws SQLException
-        {
-            if (valueListSize > 0) 
+            catch (DataSetException e)
             {
-                // Some attributes can be multivalued.
-                List values = new ArrayList(valueListSize);
-                for (int j = 0; j < valueListSize; j++) 
-                {
-                    ArrayList multiVal = new ArrayList(2);
-                    multiVal.add(rs.getString(j + 4));
-                    values.add(multiVal);
-                }
-                List lastValues = qr.getAttributeValues();
-                if (lastValues == null) 
-                {
-                    qr.setAttributeValues(values);                    
-                }
-                else 
-                {
-                    lastValues.addAll(values);
-                }
-            }
-        }
-
-        private void queryResultContinued(ResultSet rs, QueryResult qr, 
-                                          int base, int valueListSize)
-            throws SQLException
-        {
-            if (valueListSize > 0)
-            {
-                List values = qr.getAttributeValues();
-                for (int j = 0; j < valueListSize; j++)
-                {
-                    String s = rs.getString(j + 4);
-
-                    // As it's possible that multiple rows
-                    // could have the same value for a given
-                    // attribute, and we don't want to add the
-                    // same value many times, check for this
-                    // below.  See the code in the "else if"
-                    // block about 10 lines down to see how
-                    // the values lists are arranged to allow
-                    // for multiple values.
-                    List prevValues = (List) values.get(j + base);
-                    boolean newValue = true;
-                    for (int k = 0; k < prevValues.size(); k++)
-                    {
-                        if (ObjectUtils.equals(prevValues.get(k), s))
-                        {
-                            newValue = false;
-                            break;
-                        }
-                    }
-                    if (newValue) 
-                    {
-                        prevValues.add(s);
-                    }
-                }
+                throw new RuntimeException(e);	
             }
         }
     }
-
-    private static class ColumnBundle
-    {
-        int size;
-        StringBuffer select;
-        StringBuffer outerJoins;
-        String sortColumn;
-    }
-
-    private static class ResultSetAndSize
-    {
-        private ResultSet resultSet;
-        private int size;
-        ResultSetAndSize(ResultSet rs, int s)
-        {
-            resultSet = rs;
-            size = s;
-        }
-    }
-
 }
-

Modified: trunk/src/java/org/tigris/scarab/util/word/IssueSearchFactory.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/IssueSearchFactory.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/util/word/IssueSearchFactory.java&p2=trunk/src/java/org/tigris/scarab/util/word/IssueSearchFactory.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/IssueSearchFactory.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/IssueSearchFactory.java	2007-06-09 08:06:34-0700
@@ -93,11 +93,8 @@
      */
     int getMaxInstances()
     {
-	// TODO: FIXME: Should be avalon componente
-        //int max = Turbine.getConfiguration()
-        //    .getInt("scarab.concurrent.search.max", -1);
-        //return max;
-        return 2;
+	// TODO: should be a fraction of the number of connections in the connection pool;
+        return 4;
     }
 
     /**
@@ -145,76 +142,39 @@
         return search;
     }
 
-    void register()
+    synchronized void register()
         throws ScarabException, InterruptedException
     {
-        if (maxInstances <= 0) 
+        long starttime = System.currentTimeMillis();
+        while (numActive > maxInstances) 
         {
-            throw new MaxConcurrentSearchException(L10NKeySet.ExceptionSearchIsNotAllowed);
-        }
-        else 
-        {
-            synchronized (this)
+            try 
             {
-                long starttime = System.currentTimeMillis();
-                // check if we can create one
-                while (numActive >= maxInstances) 
-                {
-                    // we can't create a new instance at this moment
-                    try 
-                    {
-                        if (maxWait > 0)
-                        {
-                            wait(maxWait);
-                        }
-                        else if (maxWait < 0) 
-                        {
-                            wait(); // no god idea becasue potential for frozen Scarab [HD]
-                        } 
-                        else // maxWait == 0 
-                        {
-                            throw new MaxConcurrentSearchException(
-                                L10NKeySet.ExceptionMaxConcurrentSearch,
-                                ""+this.getMaxWait()
-                                );
-                        }
-                    }
-                    catch(InterruptedException e) 
-                    {
-                        notify();
-                        throw e; //EXCEPTION
-                    }
-                    if(maxWait > 0 && 
-                       ((System.currentTimeMillis() - starttime) >= maxWait)) 
-                    {
-                        throw new MaxConcurrentSearchException(
-                            L10NKeySet.ExceptionMaxConcurrentSearch,
-                            ""+this.getMaxWait()
-                            );
-                    }
-                }    
-                numActive++;
+                wait(1000);
             }
-        }
+            catch(InterruptedException e) 
+            {
+                notify();
+                throw e;
+            }
+            if(System.currentTimeMillis() - starttime > maxWait) 
+            {
+                throw new MaxConcurrentSearchException(
+                    L10NKeySet.ExceptionMaxConcurrentSearch,
+                    ""+this.getMaxWait()
+                    );
+            }
+        }    
+        numActive++;
     }
 
-    public void notifyDone()
+    synchronized public void notifyDone()
     {
-        if (maxInstances > 0) 
+        if (numActive > 0) 
         {
-            synchronized (this)
-            {
-                // normally always true, but false is a possibility
-                if (numActive > 0) 
-                {
-                    numActive--;   
-                }
-                if (maxWait != 0) 
-                {
-                    this.notifyAll(); // give wait'ers a chance at it
-                }
-            }
+            numActive--;   
         }
+        this.notifyAll();
     }
 }
 

Modified: trunk/src/java/org/tigris/scarab/util/word/QueryResult.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/QueryResult.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/util/word/QueryResult.java&p2=trunk/src/java/org/tigris/scarab/util/word/QueryResult.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/QueryResult.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/QueryResult.java	2007-06-09 08:06:34-0700
@@ -48,20 +48,21 @@
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.Date;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Iterator;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.torque.TorqueException;
-import org.tigris.scarab.om.Module;
-import org.tigris.scarab.om.RModuleIssueType;
+import org.tigris.scarab.om.AttributeValue;
+import org.tigris.scarab.om.AttributeValueManager;
 import org.tigris.scarab.om.RModuleUserAttribute;
+import org.tigris.scarab.om.Issue;
+import org.tigris.scarab.om.IssueType;
+import org.tigris.scarab.om.IssueManager;
 import org.tigris.scarab.om.ScarabUser;
-import org.tigris.scarab.om.ScarabUserImplPeer;
 import org.tigris.scarab.tools.ScarabLocalizationTool;
 import org.tigris.scarab.tools.localization.L10NKeySet;
-
 /**
  * This class is created by the IssueSearch object to contain a single result.
  * It represents a row on the IssueList.vm screen.  It is mostly
@@ -72,96 +73,49 @@
  */
 public class QueryResult
 {
-    /** the search that created this QueryResult */
-    private final IssueSearch search;
-    private String issueId;
-    private String idPrefix;
-    private String idCount;
-    private String uniqueId;
+    private final Long issueId;
+    private final List issueListAttributeColumns;
+    private final Integer sortAttrId;
+    private final Long sortValueId;
+    private final ScarabLocalizationTool L10N;
+    
     private List attributeValues;
-    private Integer moduleId;
-    private Integer issueTypeId;
-    private Integer createdBy;
-    private Date createdDate;
-    private Date modifiedDate;
-    private Integer modifiedBy;
 
     /**
      * Ctor. Should only be called by an IssueSearch.
      *
      * @param search the <code>IssueSearch</code> that created this result
      */
-    QueryResult(IssueSearch search)
+    QueryResult(Long issueId, List issueListAttributeColumns, Integer sortAttrId, Long sortValueId, ScarabLocalizationTool L10N )
     {
-        this.search = search;
+        this.issueId = issueId;
+        this.issueListAttributeColumns = issueListAttributeColumns;
+        this.sortAttrId=sortAttrId;
+        this.sortValueId=sortValueId;
+        this.L10N = L10N;        
     }
 
+    private final Issue getIssue()
+        throws TorqueException
+        {
+    	return IssueManager.getInstance(issueId);
+    }
     /**
      * Get the IssueId value.
      * @return the IssueId value.
      */
     public final String getIssueId()
     {
-        return issueId;
-    }
-
-    /**
-     * Set the IssueId value.
-     * @param newIssueId The new IssueId value.
-     */
-    public final void setIssueId(String newIssueId)
-    {
-        this.issueId = newIssueId;
-    }
-
-    /**
-     * Get the IdPrefix value.
-     * @return the IdPrefix value.
-     */
-    public final String getIdPrefix()
-    {
-        return idPrefix;
-    }
-
-    /**
-     * Set the IdPrefix value.
-     * @param newIdPrefix The new IdPrefix value.
-     */
-    public final void setIdPrefix(String newIdPrefix)
-    {
-        this.idPrefix = newIdPrefix;
-    }
-
-    /**
-     * Get the IdCount value.
-     * @return the IdCount value.
-     */
-    public final String getIdCount()
-    {
-        return idCount;
+        return issueId.toString();
     }
 
     /**
-     * Set the IdCount value.
-     * @param newIdCount The new IdCount value.
-     */
-    public final void setIdCount(String newIdCount)
-    {
-        this.idCount = newIdCount;
-    }
-
-
-    /**
      * Combines getIdPrefix() and getIdCount()
      */
     public final String getUniqueId()
+        throws TorqueException
     {
-        if (uniqueId == null) 
-        {
-            uniqueId = getIdPrefix() + getIdCount();
-        }
-            
-        return uniqueId;
+        return getIssue().getUniqueId();
     }
 
     /**
@@ -169,261 +123,123 @@
      * @return the AttributeValues value.
      */
     public final List getAttributeValues()
+        throws TorqueException
     {
-        return attributeValues;
-    }
-
-    /**
-     * Get the AttributeValues value.
-     * @return the AttributeValues value.
-     */
-    public final List getAttributeValuesAsCSV()
-    {
-        List result = null;
-        if (attributeValues != null) 
+        if(attributeValues==null)
         {
-            result = new ArrayList(attributeValues.size());
-            for (Iterator i = attributeValues.iterator(); i.hasNext();) 
+            attributeValues = new ArrayList();
+            for(int j=0;j<issueListAttributeColumns.size();j++)
             {
-                String csv = null;
-                List multiVal = (List)i.next();
-                if (multiVal.size() == 1) 
-                {
-                    csv = (String)multiVal.get(0);    
-                    if (csv == null) 
-                    {
-                        csv = "";
-                    }
-                }
-                else 
+                RModuleUserAttribute rmua = (RModuleUserAttribute)issueListAttributeColumns.get(j);
+
+                List value = null;
+                if(rmua.isInternal())
                 {
-                    StringBuffer sb = new StringBuffer();
-                    boolean addComma = false;
-                    for (Iterator j = multiVal.iterator(); j.hasNext();) 
-                    {
-                        if (addComma) 
-                        {
-                            sb.append(", ");
-                        }
-                        else 
-                        {
-                            addComma = true;
-                        }
-                            
-                        sb.append(j.next().toString());
-                    }
-                    csv = sb.toString();
+                	String attributeId = rmua.getInternalAttribute();
+                    value = getInternalAttributeValue(attributeId);
                 }
-                result.add(csv);
-            }
-        }
-            
-        return result;
+                else
+                {
+                    Integer attributeId = rmua.getAttributeId();                
+                    value = getAttributeValue(attributeId);
+                }                    
+                attributeValues.add(value);
+            }                                
+        }        
+        return attributeValues;
     }
 
-    /**
-     * Populate any attribute considered 'internal' with the proper value. To decide
-     * which should be filled, it will use the list 'preferences', which shares the same
-     * order than the attribute list.
-     * 
-     * @param preferences
-     */
-    public void populateInternalAttributes(List preferences)
-    {
-        this.populateInternalAttributes(preferences, null);
-    }
-    
-    /**
-     * Populate, including localization of dates, any attribute considered 'internal' with
-     * the proper value. To decide which should be filled, it will use the list 'preferences', which shares the same
-     * order than the attribute list.
-     * 
-     * @param preferences
-     */    
-    public void populateInternalAttributes(List preferences, ScarabLocalizationTool l10n)
-    {
-        if (preferences == null)
-        {
-            // No preferences, no need to do anything
-            return;
-        }
+	/**
+	 * @param attributeId
+	 */
+	private List getAttributeValue(Integer attributeId)
+        throws TorqueException
+	{
+        List value = new ArrayList();
+        List attributeValue = getIssue().getAttributeValues(attributeId);
+        String singleValue = null;
         
-        if (l10n == null)
+        if(attributeId.equals(sortAttrId))
+	    {
+	    	if(sortValueId!=null)
+	    	{
+	    		AttributeValue sortValue = AttributeValueManager.getInstance(sortValueId);
+	    		singleValue = sortValue.getDisplayValue();	    		
+	    	}
+	    	else
+	    	{
+	    		singleValue = "";
+	    	}
+        	value.add(singleValue);
+	    }
+	    else
+	    {
+            for(int i=0;i<attributeValue.size();i++)
+		    {
+		        singleValue = ((AttributeValue)attributeValue.get(i)).getDisplayValue();
+		        value.add( singleValue );
+		    }
+		}
+		return value;
+	}
+
+	/**
+	 * @param attributeId
+	 */
+	private List getInternalAttributeValue(String attributeId)
+        throws TorqueException
+	{
+        List value = new ArrayList();
+        if (attributeId.equals(RModuleUserAttribute.CREATED_BY.getName()))
         {
-            l10n = new ScarabLocalizationTool();
+            ScarabUser user = getIssue().getCreatedBy();
+            value.add(user.getUserName());
         }
-
-        for (int i=0; i<preferences.size(); i++)
+        else if (attributeId.equals(RModuleUserAttribute.CREATED_DATE.getName()))
         {
-            RModuleUserAttribute rmua = (RModuleUserAttribute)preferences.get(i);
-            if (rmua.isInternal())
-            {
-                List list = new ArrayList();
-                if (rmua.getInternalAttribute().equals(RModuleUserAttribute.CREATED_BY.getName()))
-                {
-                    ScarabUser user = this.getCreatedByUser();
-                    if (user != null)
-                    {
-                        list.add(user.getName());
-                    }
-                }
-                else if (rmua.getInternalAttribute().equals(RModuleUserAttribute.CREATED_DATE.getName()))
-                {
-                    Date date = this.getCreatedDate();
-                    if (date != null)
-                    {
-                        DateFormat df = new SimpleDateFormat(L10NKeySet.ShortDatePattern.getMessage(l10n));
-                        list.add(df.format(this.getCreatedDate()));
-                    }
-                }
-                else if (rmua.getInternalAttribute().equals(RModuleUserAttribute.MODIFIED_BY.getName()))
-                {
-                    ScarabUser user = this.getModifiedByUser();
-                    if (user != null)
-                    {
-                        list.add(user.getName());
-                    }
-                }
-                else if (rmua.getInternalAttribute().equals(RModuleUserAttribute.MODIFIED_DATE.getName()))
-                {
-                    Date date = this.getModifiedDate();
-                    if (date != null)
-                    {
-                        DateFormat df = new SimpleDateFormat(L10NKeySet.ShortDatePattern.getMessage(l10n));
-                        list.add(df.format(this.getModifiedDate()));
-                    }
-                }
-                attributeValues.set(i, list);
-            }
+            DateFormat df = new SimpleDateFormat(L10NKeySet.ShortDatePattern.getMessage(L10N));
+            value.add(df.format(getIssue().getCreatedDate()));
         }
-    }
-    
-    /**
-     * Set the AttributeValues value.
-     * @param newAttributeValues The new AttributeValues value.
-     */
-    public final void setAttributeValues(List newAttributeValues)
-    {
-        this.attributeValues = newAttributeValues;
-    }
-        
-
-    /**
-     * Get the ModuleId value.
-     * @return the ModuleId value.
-     */
-    public final Integer getModuleId()
-    {
-        return moduleId;
-    }
-
-    /**
-     * Set the ModuleId value.
-     * @param newModuleId The new ModuleId value.
-     */
-    public final void setModuleId(Integer newModuleId)
-    {
-        this.moduleId = newModuleId;
-    }
-
-    /**
-     * Get the <code>Module</code> related thru getModuleId().  This method
-     * provides caching so that multiple QueryResult objects in the same 
-     * resultset save db hits.
-     */
-    public final Module getModule()
-        throws TorqueException
-    {
-        return search.getModule(moduleId);
-    }
-
-    /**
-     * Get the IssueTypeId value.
-     * @return the IssueTypeId value.
-     */
-    public final Integer getIssueTypeId()
-    {
-        return issueTypeId;
-    }
-
-    /**
-     * Set the IssueTypeId value.
-     * @param newIssueTypeId The new IssueTypeId value.
-     */
-    public final void setIssueTypeId(Integer newIssueTypeId)
-    {
-        this.issueTypeId = newIssueTypeId;
-    }
-
-    /**
-     * Get the <code>RModuleIssueType</code> related thru getModuleId() and 
-     * getIssueTypeId().  This method provides caching so that multiple 
-     * QueryResult objects in the same resultset save db hits.
-     */
-    public final RModuleIssueType getRModuleIssueType()
-        throws TorqueException
-    {
-        return search.getRModuleIssueType(moduleId, issueTypeId);
-    }
-
-    public void setCreatedBy(Integer createdBy)
-    {
-        this.createdBy = createdBy;
-        
-    }
-    
-    public Integer getCreatedBy()
-    {
-        return this.createdBy;
-    }
-    
-    public ScarabUser getCreatedByUser()
-    {
-        ScarabUser user = null;
-        try
+        else if (attributeId.equals(RModuleUserAttribute.MODIFIED_BY.getName()))
         {
-            user = ScarabUserImplPeer.retrieveScarabUserImplByPK(this.createdBy);
+            ScarabUser user = getIssue().getModifiedBy();
+            value.add(user.getUserName());
         }
-        catch (Exception e)
+        else if (attributeId.equals(RModuleUserAttribute.MODIFIED_DATE.getName()))
         {
+            DateFormat df = new SimpleDateFormat(L10NKeySet.ShortDatePattern.getMessage(L10N));
+            value.add(df.format(getIssue().getModifiedDate()));
         }
-        return user;
-    }
-    public void setCreatedDate(Date created)
-    {
-        this.createdDate = created;
-    }
-    public Date getCreatedDate()
-    {
-        return this.createdDate;
-    }
-    public void setModifiedBy(Integer modified)
-    {
-        this.modifiedBy = modified;
-    }
-    public Integer getModifiedBy()
-    {
-        return this.modifiedBy;
-    }
-    
-    public ScarabUser getModifiedByUser()
-    {
-        ScarabUser user = null;
-        try
+        else if (attributeId.equals(RModuleUserAttribute.MODULE.getName()))
         {
-            user = ScarabUserImplPeer.retrieveScarabUserImplByPK(this.modifiedBy);
+            value.add(getIssue().getModule().getRealName());
         }
-        catch (Exception e)
+        else if (attributeId.equals(RModuleUserAttribute.ISSUE_TYPE.getName()))
         {
+            IssueType isueType = getIssue().getIssueType();
+            value.add(isueType.getDisplayName(getIssue().getModule()));
         }
-        return user;
-    }
-    public void setModifiedDate(Date modifiedDate )
-    {
-        this.modifiedDate = modifiedDate;
-    }
-    public Date getModifiedDate()
+		return value;
+	}
+	
+    /**
+     * Get the AttributeValues value.
+     * @return the AttributeValues value.
+     */
+    public final List getAttributeValuesAsCSV()
+        throws TorqueException
     {
-        return this.modifiedDate;
+        List result = null;
+        if (getAttributeValues() != null) 
+        {
+            result = new ArrayList(getAttributeValues().size());
+            for (Iterator i = getAttributeValues().iterator(); i.hasNext();) 
+            {
+                List multiVal = (List)i.next();
+                String csv = StringUtils.join(multiVal.iterator(), ", ");
+                result.add(csv);
+            }
+        }            
+        return result;
     }
 }

Modified: trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java&p2=trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java	(original)
+++ trunk/src/java/org/tigris/scarab/util/word/SearchFactory.java	2007-06-09 08:06:34-0700
@@ -60,7 +60,7 @@
 public class SearchFactory {
     private static SearchIndex searchIndex;
 
-    public static SearchIndex getInstance() throws InstantiationException 
+    public static SearchIndex getInstance()  
     {
         SearchIndex result = searchIndex;
 

Modified: trunk/src/java/org/tigris/scarab/xmlrpc/SimpleHandler.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/java/org/tigris/scarab/xmlrpc/SimpleHandler.java?view=diff&rev=10445&p1=trunk/src/java/org/tigris/scarab/xmlrpc/SimpleHandler.java&p2=trunk/src/java/org/tigris/scarab/xmlrpc/SimpleHandler.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/java/org/tigris/scarab/xmlrpc/SimpleHandler.java	(original)
+++ trunk/src/java/org/tigris/scarab/xmlrpc/SimpleHandler.java	2007-06-09 08:06:34-0700
@@ -28,6 +28,7 @@
 
 import org.apache.log4j.Category;
 import org.apache.turbine.Turbine;
+import org.apache.torque.TorqueException;
 
 
 /**
@@ -345,32 +346,28 @@
             final Attribute attribute, final String value) throws Exception
     {
     	IssueSearch search = null;
-        final Vector retValue = new Vector();
+        final Vector matchingIssueIds = new Vector();
         try
         {
             search = IssueSearchFactory.INSTANCE.getInstance(
-                  MITListManager.getAllModulesAllIssueTypesList(user), user);
-            final AttributeValue av = AttributeValue.getNewInstance(attribute, search);
-            av.setValue(value);
-            search.addAttributeValue(av);
-            final Iterator queryresults = search.getQueryResults();
+                   MITListManager.getAllModulesAllIssueTypesList(user), user);
+            search.addAttributeValue(attribute, value);
+            final List queryresults = search.getQueryResults();
 
-            while (queryresults.hasNext())
+            for(Iterator i=queryresults.iterator();i.hasNext();)
             {
-                final QueryResult qr = (QueryResult) queryresults.next();
-                retValue.add(qr.getUniqueId());
-                //log(" Adding to results "+qr.getUniqueId());
+                final QueryResult qr = (QueryResult) i.next();
+                matchingIssueIds.add(qr.getUniqueId());
             }
         }
         finally
         {
         	if(search != null)
         	{
-                search.close();
                 IssueSearchFactory.INSTANCE.notifyDone();
         	}
         }    
-        return retValue; // return matching issues
+        return matchingIssueIds;
     }
 
 }

Modified: trunk/src/test/org/tigris/scarab/feeds/QueryFeedTest.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/test/org/tigris/scarab/feeds/QueryFeedTest.java?view=diff&rev=10445&p1=trunk/src/test/org/tigris/scarab/feeds/QueryFeedTest.java&p2=trunk/src/test/org/tigris/scarab/feeds/QueryFeedTest.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/test/org/tigris/scarab/feeds/QueryFeedTest.java	(original)
+++ trunk/src/test/org/tigris/scarab/feeds/QueryFeedTest.java	2007-06-09 08:06:34-0700
@@ -44,11 +44,12 @@
  * This software consists of voluntary contributions made by many
  * individuals on behalf of CollabNet.
  */ 
+import java.util.List;
+import java.util.Collections;
 import org.tigris.scarab.om.Query;
 import org.tigris.scarab.om.QueryManager;
 import org.tigris.scarab.screens.RSSDataExport;
 import org.tigris.scarab.test.BaseScarabTestCase;
-import org.tigris.scarab.util.IteratorWithSize;
 
 import com.sun.syndication.feed.synd.SyndFeed;
 import com.sun.syndication.io.SyndFeedOutput;
@@ -63,7 +64,7 @@
     public void testCreatingFeed() throws Exception{
         Query query = QueryManager.getInstance(new Long(280));
         assertNotNull(query);
-        IteratorWithSize results = IteratorWithSize.EMPTY;
+        List results = Collections.EMPTY_LIST;
         Feed feed = new QueryFeed(query,results,null, RSSDataExport.DEFAULT_FEED_FORMAT);
         SyndFeed syndFeed = feed.getFeed();
         syndFeed.setFeedType("rss_2.0");

Modified: trunk/src/test/org/tigris/scarab/test/AllScarabTests.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/test/org/tigris/scarab/test/AllScarabTests.java?view=diff&rev=10445&p1=trunk/src/test/org/tigris/scarab/test/AllScarabTests.java&p2=trunk/src/test/org/tigris/scarab/test/AllScarabTests.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/test/org/tigris/scarab/test/AllScarabTests.java	(original)
+++ trunk/src/test/org/tigris/scarab/test/AllScarabTests.java	2007-06-09 08:06:34-0700
@@ -70,8 +70,6 @@
 import org.tigris.scarab.services.yaaficomponent.YaafiComponentServiceTest;
 import org.tigris.scarab.util.EmailLinkTest;
 import org.tigris.scarab.util.ScarabUtilTest;
-import org.tigris.scarab.util.SubsetIteratorTest;
-import org.tigris.scarab.util.SubsetIteratorWithSizeTest;
 import org.tigris.scarab.util.word.IssueSearchTest;
 import org.tigris.scarab.util.xmlissues.ImportIssuesTest;
 import org.tigris.scarab.xmlrpc.NewTicketHandlerTest;
@@ -141,15 +139,11 @@
 		// org.tigris.scarab.util
 		suite.addTestSuite(EmailLinkTest.class);
 		suite.addTestSuite(ScarabUtilTest.class);
-		suite.addTestSuite(SubsetIteratorTest.class);
-		suite.addTestSuite(SubsetIteratorWithSizeTest.class);
 		
 		// org.tigris.scarab.util.xmlissues
 		suite.addTestSuite(ImportIssuesTest.class);
 
 		suite.addTestSuite(ScarabUtilTest.class);
-		suite.addTestSuite(SubsetIteratorTest.class);
-		suite.addTestSuite(SubsetIteratorWithSizeTest.class);
         //suite.addTestSuite(IssueSearchTest.class);
 
 		suite.addTestSuite(NewTicketHandlerTest.class);

Removed: trunk/src/test/org/tigris/scarab/util/SubsetIteratorTest.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/test/org/tigris/scarab/util/SubsetIteratorTest.java?view=auto&rev=10444

Removed: trunk/src/test/org/tigris/scarab/util/SubsetIteratorWithSizeTest.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/test/org/tigris/scarab/util/SubsetIteratorWithSizeTest.java?view=auto&rev=10444

Modified: trunk/src/test/org/tigris/scarab/util/word/IssueSearchTest.java
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/test/org/tigris/scarab/util/word/IssueSearchTest.java?view=diff&rev=10445&p1=trunk/src/test/org/tigris/scarab/util/word/IssueSearchTest.java&p2=trunk/src/test/org/tigris/scarab/util/word/IssueSearchTest.java&r1=10444&r2=10445
==============================================================================
--- trunk/src/test/org/tigris/scarab/util/word/IssueSearchTest.java	(original)
+++ trunk/src/test/org/tigris/scarab/util/word/IssueSearchTest.java	2007-06-09 08:06:34-0700
@@ -46,16 +46,14 @@
  * individuals on behalf of Collab.Net.
  */ 
 
-
-import org.apache.torque.om.NumberKey;
+import java.util.List;
 import org.tigris.scarab.test.BaseScarabTestCase;
+import org.tigris.scarab.om.Attribute;
 import org.tigris.scarab.om.Module;
 import org.tigris.scarab.om.IssueType;
-import org.tigris.scarab.om.AttributeValue;
 import org.tigris.scarab.om.AttributeManager;
 import org.tigris.scarab.om.AttributeOptionManager;
 import org.tigris.scarab.om.AttributeOption;
-import org.tigris.scarab.util.IteratorWithSize;
 
 /**
  * A Testing Suite for the om.IssueSearch class.
@@ -65,7 +63,6 @@
  */
 public class IssueSearchTest extends BaseScarabTestCase
 {
-    private IssueSearch search;
 
     private int[] attributeIds = {3, 4, 6, 7, 8}; //, 9, 12};
     private int[] optionIds = {1, 8, 24, 54, 58}; //, 62, 88};
@@ -86,13 +83,10 @@
         throws Exception
     {
         IssueSearch search = getSearch();
-        AttributeValue platformAV = AttributeValue
-            .getNewInstance(getPlatformAttribute(), search);
         AttributeOption sgi = 
             AttributeOptionManager.getInstance(new Integer(21));
-        platformAV.setAttributeOption(sgi);
-        search.addAttributeValue(platformAV);
-        IteratorWithSize results = search.getQueryResults();
+        search.addAttributeValue(getPlatformAttribute(), sgi);
+        List results = search.getQueryResults();
         assertTrue("Should be one result.", (results.size() == 1));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
@@ -101,13 +95,10 @@
         throws Exception
     {
         IssueSearch search = getSearch();
-        AttributeValue platformAV = AttributeValue
-            .getNewInstance(getPlatformAttribute(), search);
         AttributeOption notsgi = 
             AttributeOptionManager.getInstance(new Integer(20));
-        platformAV.setAttributeOption(notsgi);
-        search.addAttributeValue(platformAV);
-        IteratorWithSize results = search.getQueryResults();
+        search.addAttributeValue(getPlatformAttribute(), notsgi);
+        List results = search.getQueryResults();
         assertTrue("Should be no result.", (results.size() == 0));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
@@ -122,13 +113,10 @@
         throws Exception
     {
         IssueSearch search = getSearch();
-        AttributeValue statusAV = AttributeValue.getNewInstance(
-                getVoteAttribute(), search);
         AttributeOption empty = 
             AttributeOptionManager.getInstance(new Integer(0));
-        statusAV.setAttributeOption(empty);
-        search.addAttributeValue(statusAV);
-        IteratorWithSize results = search.getQueryResults();
+        search.addAttributeValue(getVoteAttribute(), empty);
+        List results = search.getQueryResults();
         assertTrue("Should be ONE result.", (results.size() == 1));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
@@ -137,9 +125,9 @@
         throws Exception
     {
         IssueSearch search = getSearch();
-        search.addUserCriteria(getUser5().getUserId().toString(), 
+        search.addUserSearch(getUser5().getUserId().toString(), 
                                IssueSearch.ANY_KEY);
-        IteratorWithSize results = search.getQueryResults();
+        List results = search.getQueryResults();
         assertTrue("Should be one result.", (results.size() == 1));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
@@ -148,9 +136,9 @@
         throws Exception
     {
         IssueSearch search = getSearch();
-        search.addUserCriteria(getUser5().getUserId().toString(), 
+        search.addUserSearch(getUser5().getUserId().toString(), 
                                IssueSearch.CREATED_BY_KEY);
-        IteratorWithSize results = search.getQueryResults();
+        List results = search.getQueryResults();
         assertTrue("Should be one result.", (results.size() == 1));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
@@ -159,22 +147,21 @@
         throws Exception
     {
         IssueSearch search = getSearch();
-        search.addUserCriteria(getUser5().getUserId().toString(), 
+        search.addUserSearch(getUser5().getUserId().toString(), 
             getAssignAttribute().getAttributeId().toString());
-        IteratorWithSize results = search.getQueryResults();
+        List results = search.getQueryResults();
         assertTrue("Should be no results.", (results.size() == 0));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
 
-    // these seem to cause timeouts
-    public void OFFtestUserWithAssignedToAndCreatedDate()
+    public void testUserWithAssignedToAndCreatedDate()
         throws Exception
     {
         IssueSearch search = getSearch();
-        search.addUserCriteria(getUser5().getUserId().toString(), 
+        search.addUserSearch(getUser5().getUserId().toString(), 
             getAssignAttribute().getAttributeId().toString());
-        search.setMinDate("01/01/2000");
-        IteratorWithSize results = search.getQueryResults();
+        search.setMinCreationDate("01/01/2000");
+        List results = search.getQueryResults();
         assertTrue("Should be no results.", (results.size() == 0));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
@@ -184,65 +171,14 @@
         throws Exception
     {
         IssueSearch search = getSearch();
-        AttributeValue platformAV = AttributeValue
-            .getNewInstance(getPlatformAttribute(), search);
         AttributeOption sgi = 
             AttributeOptionManager.getInstance(new Integer(21));
-        platformAV.setAttributeOption(sgi);
-        search.addAttributeValue(platformAV);
-        search.addUserCriteria(getUser5().getUserId().toString(), 
+        search.addAttributeValue(getPlatformAttribute(), sgi);
+        search.addUserSearch(getUser5().getUserId().toString(), 
                                IssueSearch.ANY_KEY);
-        IteratorWithSize results = search.getQueryResults();
+        List results = search.getQueryResults();
         assertTrue("Should be one result.", (results.size() == 1));
         IssueSearchFactory.INSTANCE.notifyDone();
     }
-
-
-    public void OFFtestLargeQuery()
-        throws Exception
-    {
-        IssueSearch search = getSearch();
-        search.setMinDate("01/01/2000"); // 1
-        AttributeValue av;
-        AttributeOption o;
-        for (int i = 0; i < attributeIds.length; i++) 
-        {
-            av = AttributeValue.getNewInstance(AttributeManager.getInstance(
-                 new Integer(attributeIds[i])), search);     
-            o = AttributeOptionManager.getInstance(new Integer(optionIds[i]));
-            av.setAttributeOption(o);
-            search.addAttributeValue(av); // 6
-        }
-        
-        search.addUserCriteria(getUser5().getUserId().toString(), 
-                               IssueSearch.ANY_KEY); // 7
-
-        search.setStateChangeFromOptionId(new Integer(2));
-        search.setStateChangeToOptionId(new Integer(1)); // 8
-        search.setStateChangeFromDate("01/01/2000");
-        search.setStateChangeToDate("01/01/2004"); // 9
-
-        IteratorWithSize results = search.getQueryResults();
-        assertTrue("Should be no results.", (results.size() == 0));
-        IssueSearchFactory.INSTANCE.notifyDone();
-
-        av = AttributeValue.getNewInstance(getPlatformAttribute(), search);
-        o = AttributeOptionManager.getInstance(new Integer(21));
-        av.setAttributeOption(o);
-        System.out.println("av size=" + search.getAttributeValues().size());
-        search.addAttributeValue(av); // 11
-        System.out.println("after av size=" + search.getAttributeValues().size());
-
-        try 
-        {
-            search.getQueryResults();
-            fail("Should have thrown ComplexQueryException");            
-        }
-        catch (ComplexQueryException e)
-        {
-            // expected
-        }
-        IssueSearchFactory.INSTANCE.notifyDone();
-    }
 }
 

Modified: trunk/src/webapp/WEB-INF/templates/macros/AdvancedQueryMacro.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/macros/AdvancedQueryMacro.vm?view=diff&rev=10445&p1=trunk/src/webapp/WEB-INF/templates/macros/AdvancedQueryMacro.vm&p2=trunk/src/webapp/WEB-INF/templates/macros/AdvancedQueryMacro.vm&r1=10444&r2=10445
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/macros/AdvancedQueryMacro.vm	(original)
+++ trunk/src/webapp/WEB-INF/templates/macros/AdvancedQueryMacro.vm	2007-06-09 08:06:34-0700
@@ -22,7 +22,7 @@
 
 #set ($intake = $scarabR.getConditionalIntake($scarabG.Constant.CURRENT_QUERY))
 #set ($searchGroup = $intake.SearchIssue.mapTo($search))
-#set ($attrValues = $search.CommonAttributeValuesMap)
+#set ($attrValues = $search.getAttributeValuesMap(true))
 #set ($user = $data.User)
 
 ## we only show the edit link, if we are editing a saved query.
@@ -52,15 +52,32 @@
     $l10n.CreationDateRange
 </th>
 <td>
-    #fieldErrorMsg($searchGroup.MinDate "")
-    #fieldErrorMsg($searchGroup.MaxDate "")
-$l10n.TimeFrom:&#160;<input type="text" id="$searchGroup.MinDate.Key"
-	name="$searchGroup.MinDate.Key" value="$!searchGroup.MinDate.toString()" size="20" />
-	<a id="$searchGroup.MinDate.Key" name="dateAnchor$searchGroup.MinDate.Key" href="javascript:;" onClick="calPopup.select(document.getElementById('$searchGroup.MinDate.Key'),'$searchGroup.MinDate.Key','$l10n.ShortDatePattern');return false;"><img src="$staticLink.setPath('/images/date.gif')" border="0"/></a>
+    #fieldErrorMsg($searchGroup.MinCreationDate "")
+    #fieldErrorMsg($searchGroup.MaxCreationDate "")
+$l10n.TimeFrom:&#160;<input type="text" id="$searchGroup.MinCreationDate.Key"
+	name="$searchGroup.MinCreationDate.Key" value="$!searchGroup.MinCreationDate.toString()" size="20" />
+	<a id="$searchGroup.MinCreationDate.Key" name="dateAnchor$searchGroup.MinCreationDate.Key" href="javascript:;" onClick="calPopup.select(document.getElementById('$searchGroup.MinCreationDate.Key'),'$searchGroup.MinCreationDate.Key','$l10n.ShortDatePattern');return false;"><img src="$staticLink.setPath('/images/date.gif')" border="0"/></a>
     
-&#160;&#160;$l10n.TimeTo:&#160;<input type="text" id="$searchGroup.MaxDate.Key"
-	name="$searchGroup.MaxDate.Key" value="$!searchGroup.MaxDate.toString()" size="20" />
-	<a id="$searchGroup.MaxDate.Key" name="dateAnchor$searchGroup.MaxDate.Key" href="javascript:;" onClick="calPopup.select(document.getElementById('$searchGroup.MaxDate.Key'),'$searchGroup.MaxDate.Key','$l10n.ShortDatePattern');return false;"><img src="$staticLink.setPath('/images/date.gif')" border="0"/></a>    
+&#160;&#160;$l10n.TimeTo:&#160;<input type="text" id="$searchGroup.MaxCreationDate.Key"
+	name="$searchGroup.MaxCreationDate.Key" value="$!searchGroup.MaxCreationDate.toString()" size="20" />
+	<a id="$searchGroup.MaxCreationDate.Key" name="dateAnchor$searchGroup.MaxCreationDate.Key" href="javascript:;" onClick="calPopup.select(document.getElementById('$searchGroup.MaxCreationDate.Key'),'$searchGroup.MaxCreationDate.Key','$l10n.ShortDatePattern');return false;"><img src="$staticLink.setPath('/images/date.gif')" border="0"/></a>    
+<p><small>$l10n.format("DateEg", $l10n.ShortDateTimeDisplay)</small></p>
+</td>
+</tr>
+<tr>
+<th width="120">
+    $l10n.ChangeDateRange
+</th>
+<td>
+    #fieldErrorMsg($searchGroup.MinChangeDate "")
+    #fieldErrorMsg($searchGroup.MaxChangeDate "")
+$l10n.TimeFrom:&#160;<input type="text" id="$searchGroup.MinChangeDate.Key"
+	name="$searchGroup.MinChangeDate.Key" value="$!searchGroup.MinChangeDate.toString()" size="20" />
+	<a id="$searchGroup.MinChangeDate.Key" name="dateAnchor$searchGroup.MinChangeDate.Key" href="javascript:;" onClick="calPopup.select(document.getElementById('$searchGroup.MinChangeDate.Key'),'$searchGroup.MinChangeDate.Key','$l10n.ShortDatePattern');return false;"><img src="$staticLink.setPath('/images/date.gif')" border="0"/></a>
+    
+&#160;&#160;$l10n.TimeTo:&#160;<input type="text" id="$searchGroup.MaxChangeDate.Key"
+	name="$searchGroup.MaxChangeDate.Key" value="$!searchGroup.MaxChangeDate.toString()" size="20" />
+	<a id="$searchGroup.MaxChangeDate.Key" name="dateAnchor$searchGroup.MaxChangeDate.Key" href="javascript:;" onClick="calPopup.select(document.getElementById('$searchGroup.MaxChangeDate.Key'),'$searchGroup.MaxChangeDate.Key','$l10n.ShortDatePattern');return false;"><img src="$staticLink.setPath('/images/date.gif')" border="0"/></a>    
 <p><small>$l10n.format("DateEg", $l10n.ShortDateTimeDisplay)</small></p>
 </td>
 </tr>
@@ -79,15 +96,13 @@
 <table width="100%" border="1" cellspacing="2" cellpadding="3">
 <tr>
 #set ($userAttrs = $search.UserAttributes) 
-#set ($selectedUsers =  $data.User.SelectedUsersMap)
 ## If there is a working user map in memory, use that
 ## Otherwise check for saved query's users
-#if ($selectedUsers)
-  #set ($userList = $selectedUsers.keySet())
-#else
-  #set ($userList = $search.UserIdList)
-  #set ($usingList = "true")
+#set ($selectedUsers =  $data.User.SelectedUsersMap)
+#if (!$selectedUsers)
+   #set ($selectedUsers = $search.User.SearchUsers)
 #end
+#set ($userList = $selectedUsers.keySet())
 #if ($userList && !$userList.isEmpty())
 <th nowrap="nowrap">$l10n.Select</th>
 <th><strong>$l10n.Name</strong></th>
@@ -96,14 +111,10 @@
 <th><strong>$l10n.Association</strong></th>
 </tr>
 
-#foreach ($userId in $userList)
+#foreach ($userId in $userList) 
  #set ($user = $scarabR.getUser($userId))
  <input type="hidden" name="user_list" value="$userId"  />
- #if ($usingList.equals("true"))
-  #set ($attrIds = $data.Parameters.getStrings("user_attr_$userId"))
- #else
-  #set ($attrIds = $selectedUsers.get($userId))
- #end
+ #set ($attrIds = $selectedUsers.get($userId))
  
  #foreach($attrId in $attrIds)
  #set ($loopVar = $loopVar + 1) 
@@ -111,7 +122,7 @@
 
 #if ($userList && !$userList.isEmpty())
   <td><input type="checkbox" name="select_user" value="${userId}_$attrId"/></td>
-  <td><a href="mailto:$user.Email"><strong>$!user.Name</strong></a></td>
+  <td><a href="mailto:$user.Email"><strong>$user.Name</strong></a></td>
 #end
   <td>$user.UserName</a></td>
   <td>
@@ -185,8 +196,7 @@
  <td>
      <select name="$searchGroup.StateChangeAttributeId.Key">
      #set ( $selected = false )
-#foreach ( $attKey in $attrValues.mapIterator() )
-    #set ( $attVal = $attrValues.get($attKey) )
+#foreach ( $attVal in $attrValues )
     #if ($attVal.Attribute.isOptionAttribute())
         #set ( $attrInput = $intake.AttributeValue.mapTo($attVal) )
         #if (!$selected || $searchGroup.StateChangeAttributeId.Value == $attVal.AttributeId )
@@ -332,14 +342,13 @@
 
 #macro (queryAttributesSection $search $optionsOnly $headerLevel)
 
-#set ($attrValues = $search.CommonAttributeValuesMap)
+#set ($attrValues = $search.getAttributeValuesMap(true))
 <div class="axial">
 #if ( $search.isXMITSearch() )
  <h$headerLevel>$l10n.CommonAttributes</h$headerLevel>
  <table cellpadding="3" cellspacing="2" border="0" width="100%">
  #set ($firstTextWidget = true)
- #foreach ( $attKey in $attrValues.mapIterator() )
-     #set ( $attVal = $attrValues.get($attKey) )
+ #foreach ( $attVal in $attrValues )
      #if (!$attVal.Attribute.isUserAttribute() && (!$optionsOnly || $attVal.Attribute.isOptionAttribute()))
          #attributeWidget($attVal)
      #end     
@@ -400,7 +409,7 @@
             #set ($ref = $attrInput.Value.Key)
             #set ($datevalue = $scarabR.formatDate($attrInput.Value.value))
             #set ($datevalue_aux = "")
-            #set ($datevalue_aux = $data.parameters.get("${ref}_aux"))
+            #set ($datevalue_aux = $attVal.ChainedValue.Value)
             $l10n.RangeFrom:&#160;
             <input type="text" id="$ref" name="$ref" value="$datevalue" size="20" />
 			<a id="dateAnchor$ref" name="dateAnchor$ref" href="javascript:;" onClick="calPopup.select(document.getElementById('$ref'),'dateAnchor$ref','$l10n.ShortDatePattern');return false;"><img src="$staticLink.setPath('/images/date.gif')" border="0"/></a>

Modified: trunk/src/webapp/WEB-INF/templates/macros/GlobalMacros.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/macros/GlobalMacros.vm?view=diff&rev=10445&p1=trunk/src/webapp/WEB-INF/templates/macros/GlobalMacros.vm&p2=trunk/src/webapp/WEB-INF/templates/macros/GlobalMacros.vm&r1=10444&r2=10445
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/macros/GlobalMacros.vm	(original)
+++ trunk/src/webapp/WEB-INF/templates/macros/GlobalMacros.vm	2007-06-09 08:06:34-0700
@@ -605,25 +605,21 @@
 ## ---------------------------------------------------------------------------
 
 #macro (navigate)
- <p class="paginate">
-#set ($prevIssue=$scarabR.PrevIssue)
- #if($prevIssue)
-  #set ($prevLink = $link.setPathInfo("id", "$prevIssue").setPage($scarabR.getCurrentTemplate()))
- #foreach ($prevNextId in $data.Parameters.getStrings("issueList"))
-    #set ($dummy = $prevLink.addPathInfo("issueList", $prevNextId))
- #end
-  <a href="$prevLink">$l10n.PaginatePrevious</a> |
- #end
-$scarabR.IssuePosInList of $scarabR.CurrentSearchResultsSize
-#set ($nextIssue=$scarabR.NextIssue)
- #if ($nextIssue)
-  #set ($nextLink = $link.setPathInfo("id", "$nextIssue").setPage($scarabR.getCurrentTemplate()))
- #foreach ($prevNextId in $data.Parameters.getStrings("issueList"))
-    #set ($dummy = $nextLink.addPathInfo("issueList", $prevNextId))
- #end
-  | <a href="$nextLink">$l10n.PaginateNext</a>
+ #if ($scarabR.isIssuePartOfList())
+   <p class="paginate">
+  #set ($prevIssue=$scarabR.PrevIssue)
+  #if($prevIssue)
+   #set ($prevLink = $link.setPathInfo("id", "$prevIssue").setPage($scarabR.getCurrentTemplate()).addPathInfo("posInList", $scarabR.PrevIssuePosInList))
+   <a href="$prevLink">$l10n.PaginatePrevious</a> |
+  #end
+  $scarabR.IssuePosInList of $scarabR.CurrentSearchResultsSize
+  #set ($nextIssue=$scarabR.NextIssue)
+  #if ($nextIssue)
+   #set ($nextLink = $link.setPathInfo("id", "$nextIssue").setPage($scarabR.getCurrentTemplate()).addPathInfo("posInList", $scarabR.NextIssuePosInList))
+    | <a href="$nextLink">$l10n.PaginateNext</a>
+  #end
+  </p>
  #end
- </p>
 #end
 
 #macro (processQueryResults $action $listSize)

Modified: trunk/src/webapp/WEB-INF/templates/screens/IssueList.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/IssueList.vm?view=diff&rev=10445&p1=trunk/src/webapp/WEB-INF/templates/screens/IssueList.vm&p2=trunk/src/webapp/WEB-INF/templates/screens/IssueList.vm&r1=10444&r2=10445
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/screens/IssueList.vm	(original)
+++ trunk/src/webapp/WEB-INF/templates/screens/IssueList.vm	2007-06-09 08:06:34-0700
@@ -7,27 +7,13 @@
 
 <div class="app" id="issuelist">
 #set ($user = $data.User)
-#if (!$queryResults)
-   #set ($queryResults = $scarabR.CurrentSearchResults)
-#end
-#set ($issueListSize = $queryResults.size())
-#set ($totalCount = $issueListSize)
-
-## if results exceed limit, get subset list
-#set ($resultsPerPage = $data.Parameters.getInt('resultsPerPage', $scarabG.Constant.ISSUE_MAX_VIEW))
-#set ($pageNum = $data.Parameters.getInt('pageNum', 1))
-#set ($paginated = $resultsPerPage > 0 && $issueListSize > $resultsPerPage)
-#if ($paginated)
- #set ($queryResults = $scarabR.getPaginatedIterator($queryResults, $pageNum, $resultsPerPage))
- #set ($issueListSize = $queryResults.size())
-#end
+## $queryResults, $totalCount are supplied in context by Search.java
 
 ## The functions used to control the current query.
 #macro (queryFunctionBar $id)
 <div class="functnbar$id">
 <table>
 <tr>
-#if ($queryString)
 #if ($searchType == 'advanced' && $scarabR.hasPermission($scarabG.Permission.USER__EDIT_PREFERENCES))
 <td>
 <input type="submit" value="$l10n.SaveQuery" name="eventSubmit_doRedirecttosavequery" />&#160;
@@ -48,7 +34,6 @@
 	 href="$link.setPage('Index.vm')/action/Search/go	/$scarabR.Query.QueryId/eventSubmit_doSelectquery/foo/output/feed/feedType/atom_0.3"><img align="middle" src="$staticLink.setPath('/images/icon_atom.gif')" border="0" /></a>
 </td>
 #end
-#end
 </tr></table>
 </div>
 #end
@@ -66,8 +51,6 @@
 <input type="hidden" name="pageNum" value="$pageNum" />
 <input type="hidden" name="$scarabG.Constant.CANCEL_TEMPLATE" value="IssueList.vm" />
 
-#set ($queryString = $data.User.MostRecentQuery)
-
 #queryFunctionBar("")
 
 <h3>
@@ -92,11 +75,14 @@
 		
 #set ($sortColumn = $data.Parameters.getString('sortColumn'))
 #set ($sortInternal=$data.Parameters.getString('sortInternal'))
-#set ($sortPolarity = $data.Parameters.getString('sortPolarity', 'asc'))
+#set ($sortPolarity = $data.Parameters.getString('sortPolarity'))
 
 #if ($sortColumn)
   <input type="hidden" name="sortColumn" value="$sortColumn" />
 #end
+#if ($sortInternal)
+  <input type="hidden" name="sortInternal" value="$sortInternal" />
+#end
 #if ($sortPolarity)
   <input type="hidden" name="sortPolarity" value="$sortPolarity" />
 #end
@@ -111,31 +97,22 @@
 #end
 
 ## START RESULTS TABLE!
-#set ($showModule = $mitlist && !$mitlist.isSingleModule())
-#set ($showIssueType = $mitlist && !$mitlist.isSingleIssueType())
-#set ($listOffset = ($pageNum - 1) * $resultsPerPage)
-#set ($qrIterator = $scarabR.getIssueListIterator($queryResults, $listOffset, $totalCount))
+#set ($qrIterator = $scarabR.getIssueListIterator($queryResults, $pageNum, $resultsPerPage))
 
 <table width="100%" border="1" cellspacing="2" cellpadding="3">
   <tr> <!-- HEADER -->
   <th width="70">$l10n.Select</th>
-  #if ($showModule)
-    <th>$l10n.CapModule</th> 
-  #end
-  #if ($showIssueType)
-    <th>$l10n.IssueType</th> 
-  #end  
   <th>
      ## Issue ID column
      #prepIssueListPageLink()
      #if ((!$sortColumn || $sortColumn == 'null') && !$sortInternal)
         ## No sorting column is active, use issue ID
         #if ($sortPolarity.equals('desc'))
-           #set ($arrowLink = $link.setPathInfo('sortPolarity', 'asc').addPathInfo('sortColumn', 'null').addPathInfo('searchType', $searchType).addPathInfo("resultsPerPage","$resultsPerPage"))
-           <a href="$arrowLink"><img src="$staticLink.setPath('/images/icon_downarrow_on.gif')" width="13" height="8" alt="$l10n.SortDescending" title="$l10n.SortDescending" border="0" />$l10n.IssueId</a>
+           #set ($sortLink = $link.setPathInfo('sortPolarity', 'asc').addPathInfo('sortColumn', 'null').addPathInfo('searchType', $searchType).addPathInfo("resultsPerPage","$resultsPerPage"))
+           <a href="$sortLink"><img src="$staticLink.setPath('/images/icon_downarrow_on.gif')" width="13" height="8" alt="$l10n.SortDescending" title="$l10n.SortDescending" border="0" />$l10n.IssueId</a>
         #else
-           #set ($arrowLink = $link.setPathInfo("sortPolarity", "desc").addPathInfo("sortColumn", 'null').addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage"))
-           <a href="$arrowLink"><img src="$staticLink.setPath("/images/icon_uparrow_on.gif")" width="13" height="8" alt="$l10n.SortAscending" title="$l10n.SortAscending" border="0" />$l10n.IssueId</a>
+           #set ($sortLink = $link.setPathInfo("sortPolarity", "desc").addPathInfo("sortColumn", 'null').addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage"))
+           <a href="$sortLink"><img src="$staticLink.setPath("/images/icon_uparrow_on.gif")" width="13" height="8" alt="$l10n.SortAscending" title="$l10n.SortAscending" border="0" />$l10n.IssueId</a>
         #end
      #else
         ## Issue ID column is not the one we are sorting on
@@ -169,19 +146,13 @@
       #if ($sortColumn.equals($pref.AttributeId.toString()) || $sortInternal.equals($pref.Name))
         ## This column is the one we are currently sorting on
         #if ($sortPolarity.equals("desc"))
-          #set ($arrowLink = $link.setPathInfo("sortPolarity", "asc").setPathInfo($sort, "$sortData").addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage"))
-          <a href="$arrowLink"><img src="$staticLink.setPath("/images/icon_downarrow_on.gif")" width="13" height="8" alt="$l10n.SortDescending" title="$l10n.SortDescending" border="0" /></a>
-
-          #prepIssueListPageLink()
-          #set ($arrowLink = $link.setPathInfo("sortPolarity", "asc").setPathInfo($sort, "$sortData").addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage"))
-          <a href="$arrowLink">$value</a>
+          #set ($sortLink = $link.setPathInfo("sortPolarity", "asc").setPathInfo($sort, "$sortData").addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage").toString())
+          <a href="$sortLink"><img src="$staticLink.setPath("/images/icon_downarrow_on.gif")" width="13" height="8" alt="$l10n.SortDescending" title="$l10n.SortDescending" border="0" /></a>
+          <a href="$sortLink">$value</a>
         #else
-          #set ($arrowLink = $link.setPathInfo("sortPolarity", "desc").setPathInfo($sort, "$sortData").addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage"))
-          <a href="$arrowLink"><img src="$staticLink.setPath("/images/icon_uparrow_on.gif")" width="13" height="8" alt="$l10n.SortAscending" title="$l10n.SortAscending" border="0" /></a>
-
-          #prepIssueListPageLink()
-          #set ($arrowLink = $link.setPathInfo("sortPolarity", "desc").setPathInfo($sort, "$sortData").addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage"))
-          <a href="$arrowLink">$value</a>
+          #set ($sortLink = $link.setPathInfo("sortPolarity", "desc").setPathInfo($sort, "$sortData").addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage").toString())
+          <a href="$sortLink"><img src="$staticLink.setPath("/images/icon_uparrow_on.gif")" width="13" height="8" alt="$l10n.SortAscending" title="$l10n.SortAscending" border="0" /></a>
+          <a href="$sortLink">$value</a>
         #end
       #else
         #set ($sortLink = $link.setPathInfo($sort, "$sortData").setPathInfo("sortPolarity", "$sortPolarity").addPathInfo("searchType","$searchType").addPathInfo("resultsPerPage","$resultsPerPage"))
@@ -198,12 +169,6 @@
    <input type="hidden" name="all_issue_ids" value="$record.UniqueId" />
    <input type="checkbox" name="issue_ids" value="$record.UniqueId" />
   </td>
-  #if ($showModule)
-  <td>$record.Module.RealName</td> 
-  #end
-  #if ($showIssueType)
-  <td>$scarabR.getIssue($record.UniqueId).RModuleIssueType.DisplayName</td> 
-  #end
   <td><a href="$link">$record.UniqueId</a></td>
   #if (!$record.AttributeValuesAsCSV)
     <td>$scarabR.getIssue($record.UniqueId).DefaultText</td>
@@ -213,13 +178,7 @@
     #if ($value.length() == 0)
       -------
     #else
-      #set ($attributeType = $scarabR.getAttributeType($velocityCount) )
- 
-      #if ( $attributeType && $attributeType == "date")
-        $scarabR.formatDate($value)    
-      #else
-        $value 
-      #end
+      $value 
     #end
     </td>
   #end

Modified: trunk/src/webapp/WEB-INF/templates/screens/Search.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/Search.vm?view=diff&rev=10445&p1=trunk/src/webapp/WEB-INF/templates/screens/Search.vm&p2=trunk/src/webapp/WEB-INF/templates/screens/Search.vm&r1=10444&r2=10445
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/screens/Search.vm	(original)
+++ trunk/src/webapp/WEB-INF/templates/screens/Search.vm	2007-06-09 08:06:34-0700
@@ -16,7 +16,6 @@
 #set ($issueType = $mitlist.IssueType)
 #set ($searchTextAttributes = $search.QuickSearchTextAttributeValues)
 #set ($searchValues = $search.QuickSearchOptionAttributeValues)
-#set ($attrValues = $search.ModuleAttributeValuesMap)
 
 <div align="right"><a href="$link.setPage("AdvancedQuery.vm").addPathInfo("action", "Search").addPathInfo("eventSubmit_doSetquerytarget", "foo")">$l10n.AdvancedQuery</a></div>
 

Modified: trunk/src/webapp/WEB-INF/templates/screens/ViewIssue.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/ViewIssue.vm?view=diff&rev=10445&p1=trunk/src/webapp/WEB-INF/templates/screens/ViewIssue.vm&p2=trunk/src/webapp/WEB-INF/templates/screens/ViewIssue.vm&r1=10444&r2=10445
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/screens/ViewIssue.vm	(original)
+++ trunk/src/webapp/WEB-INF/templates/screens/ViewIssue.vm	2007-06-09 08:06:34-0700
@@ -34,7 +34,6 @@
       #printCollisionInfo()
     #end
 
-    #set ($prevNextList = $data.Parameters.getStrings("issueList"))
     #set ($attrValues = $currentIssue.ModuleAttributeValuesMap)
 
     <form method="post" name="form" enctype="multipart/form-data" action="$link.setPage("ViewIssue.vm")">
@@ -44,17 +43,13 @@
       #if ($fullHistory)
         <input type="hidden" name="fullHistory" value="$fullHistory" />
       #end
-      #foreach ($prevNextId in $prevNextList)
-        <input type="hidden" name="issueList" value="$prevNextId" />
-      #end
 
       #viewIssueTab()
 
       #macro (initializeTabLink)
         #set ($tabLink = $link.setPage("ViewIssue.vm").addPathInfo("id", "$currentIssue.UniqueId").addPathInfo("eventSubmit_doSetissueview", "foo").setAction("ViewIssue"))
-
-        #foreach ($prevNextId in $prevNextList)
-          #set ($dummy = $tabLink.addPathInfo("issueList", $prevNextId))
+        #if ($scarabR.isIssuePartOfList())
+           #set ($dummy = $tabLink.addPathInfo("posInList", $scarabR.IssuePosInList ))
         #end
       #end
 
@@ -63,15 +58,14 @@
         #if (!$singleScreenOnly)
           <div align="right"><small><a href="$tabLink.addPathInfo("tab", "1")">$l10n.ViewAsTabs</a></small></div>
         #end
-        #if ($data.User.hasMostRecentQuery() && $prevNextList)
-          #navigate()
-        #end
+
+        #navigate()
+
       #elseif (!$multiple.equals("true"))
         #initializeTabLink()
         <div align="right"><small><a href="$tabLink.addPathInfo("tab", "all")">$l10n.ViewAsSingleScreen</a></small></div>
-        #if ($data.User.hasMostRecentQuery() && $prevNextList)
-          #navigate()
-        #end
+
+        #navigate()
 
         <div class="tabs">
           <table cellpadding="3" cellspacing="0" border="0">

Modified: trunk/src/webapp/WEB-INF/templates/screens/help/UserQuery.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/help/UserQuery.vm?view=diff&rev=10445&p1=trunk/src/webapp/WEB-INF/templates/screens/help/UserQuery.vm&p2=trunk/src/webapp/WEB-INF/templates/screens/help/UserQuery.vm&r1=10444&r2=10445
==============================================================================
--- trunk/src/webapp/WEB-INF/templates/screens/help/UserQuery.vm	(original)
+++ trunk/src/webapp/WEB-INF/templates/screens/help/UserQuery.vm	2007-06-09 08:06:34-0700
@@ -18,7 +18,6 @@
             <li><a href="$link.setPage("help,UserQueryText.vm")">$l10n.TextQueries</a></li>
             <li><a href="$link.setPage("help,UserQuerySaved.vm")">$l10n.SavedQueries</a></li>
             <li><a href="$link.setPage("help,UserQueryCrossProject.vm")">$l10n.CrossProjectQueries</a></li>
-            <li><a href="$link.setPage("help,UserQueryComplex.vm")">$l10n.QueryLimits</a></li>
            </ul>
            </li>
           <li><a href="$link.setPage("help,UserReports.vm")">$l10n.HelpReports</a></li>

Removed: trunk/src/webapp/WEB-INF/templates/screens/help/UserQueryComplex.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/screens/help/UserQueryComplex.vm?view=auto&rev=10444

Removed: trunk/src/webapp/WEB-INF/templates/snippets/ComplexQueryHelpLink.vm
Url: http://scarab.tigris.org/source/browse/scarab/trunk/src/webapp/WEB-INF/templates/snippets/ComplexQueryHelpLink.vm?view=auto&rev=10444
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.