0001: package org.tigris.scarab.tools;
0002:
0003: /* ================================================================
0004: * Copyright (c) 2000-2003 CollabNet. All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions are
0008: * met:
0009: *
0010: * 1. Redistributions of source code must retain the above copyright
0011: * notice, this list of conditions and the following disclaimer.
0012: *
0013: * 2. Redistributions in binary form must reproduce the above copyright
0014: * notice, this list of conditions and the following disclaimer in the
0015: * documentation and/or other materials provided with the distribution.
0016: *
0017: * 3. The end-user documentation included with the redistribution, if
0018: * any, must include the following acknowlegement: "This product includes
0019: * software developed by Collab.Net <http://www.Collab.Net/>."
0020: * Alternately, this acknowlegement may appear in the software itself, if
0021: * and wherever such third-party acknowlegements normally appear.
0022: *
0023: * 4. The hosted project names must not be used to endorse or promote
0024: * products derived from this software without prior written
0025: * permission. For written permission, please contact info@collab.net.
0026: *
0027: * 5. Products derived from this software may not use the "Tigris" or
0028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
0029: * prior written permission of Collab.Net.
0030: *
0031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
0035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
0037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
0039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
0040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
0041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0042: *
0043: * ====================================================================
0044: *
0045: * This software consists of voluntary contributions made by many
0046: * individuals on behalf of Collab.Net.
0047: */
0048:
0049: import java.text.DateFormat;
0050: import java.util.ArrayList;
0051: import java.util.Arrays;
0052: import java.util.Calendar;
0053: import java.util.Collections;
0054: import java.util.Comparator;
0055: import java.util.HashMap;
0056: import java.util.Hashtable;
0057: import java.util.Iterator;
0058: import java.util.List;
0059: import java.util.Locale;
0060: import java.util.Map;
0061: import java.util.TimeZone;
0062:
0063: import javax.servlet.http.HttpSession;
0064:
0065: import org.apache.commons.collections.map.LinkedMap;
0066: import org.apache.commons.lang.StringUtils;
0067: import org.apache.fulcrum.intake.Intake;
0068: import org.apache.fulcrum.intake.model.Field;
0069: import org.apache.fulcrum.intake.model.Group;
0070: import org.apache.fulcrum.localization.Localization;
0071: import org.apache.fulcrum.parser.ParameterParser;
0072: import org.apache.fulcrum.parser.StringValueParser;
0073: import org.apache.fulcrum.pool.Recyclable;
0074: import org.apache.torque.TorqueException;
0075: import org.apache.torque.om.ComboKey;
0076: import org.apache.torque.om.NumberKey;
0077: import org.apache.torque.om.SimpleKey;
0078: import org.apache.torque.util.Criteria;
0079: import org.apache.turbine.RunData;
0080: import org.apache.turbine.TemplateContext;
0081: import org.apache.turbine.Turbine;
0082: import org.apache.turbine.services.pull.ApplicationTool;
0083: import org.apache.turbine.tool.IntakeTool;
0084: import org.tigris.scarab.attribute.DateAttribute;
0085: import org.tigris.scarab.om.Attachment;
0086: import org.tigris.scarab.om.AttachmentManager;
0087: import org.tigris.scarab.om.Attribute;
0088: import org.tigris.scarab.om.AttributeGroup;
0089: import org.tigris.scarab.om.AttributeGroupManager;
0090: import org.tigris.scarab.om.AttributeManager;
0091: import org.tigris.scarab.om.AttributeOption;
0092: import org.tigris.scarab.om.AttributeOptionManager;
0093: import org.tigris.scarab.om.AttributeOptionPeer;
0094: import org.tigris.scarab.om.AttributePeer;
0095: import org.tigris.scarab.om.AttributeValue;
0096: import org.tigris.scarab.om.Depend;
0097: import org.tigris.scarab.om.DependManager;
0098: import org.tigris.scarab.om.FrequencyPeer;
0099: import org.tigris.scarab.om.Issue;
0100: import org.tigris.scarab.om.IssueManager;
0101: import org.tigris.scarab.om.IssueTemplateInfo;
0102: import org.tigris.scarab.om.IssueTemplateInfoManager;
0103: import org.tigris.scarab.om.IssueTemplateInfoPeer;
0104: import org.tigris.scarab.om.IssueType;
0105: import org.tigris.scarab.om.IssueTypeManager;
0106: import org.tigris.scarab.om.MITList;
0107: import org.tigris.scarab.om.MITListItem;
0108: import org.tigris.scarab.om.MITListItemManager;
0109: import org.tigris.scarab.om.MITListManager;
0110: import org.tigris.scarab.om.Module;
0111: import org.tigris.scarab.om.ModuleManager;
0112: import org.tigris.scarab.om.ParentChildAttributeOption;
0113: import org.tigris.scarab.om.Query;
0114: import org.tigris.scarab.om.QueryManager;
0115: import org.tigris.scarab.om.QueryPeer;
0116: import org.tigris.scarab.om.RModuleAttribute;
0117: import org.tigris.scarab.om.RModuleAttributeManager;
0118: import org.tigris.scarab.om.RModuleIssueType;
0119: import org.tigris.scarab.om.RModuleIssueTypePeer;
0120: import org.tigris.scarab.om.ROptionOption;
0121: import org.tigris.scarab.om.ReportManager;
0122: import org.tigris.scarab.om.ScarabUser;
0123: import org.tigris.scarab.om.ScarabUserImplPeer;
0124: import org.tigris.scarab.om.ScarabUserManager;
0125: import org.tigris.scarab.om.ScopePeer;
0126: import org.tigris.scarab.om.Transition;
0127: import org.tigris.scarab.om.TransitionPeer;
0128: import org.tigris.scarab.reports.ReportBridge;
0129: import org.tigris.scarab.services.cache.ScarabCache;
0130: import org.tigris.scarab.tools.localization.L10NKeySet;
0131: import org.tigris.scarab.tools.localization.L10NMessage;
0132: import org.tigris.scarab.tools.localization.Localizable;
0133: import org.tigris.scarab.util.AnonymousUserUtil;
0134: import org.tigris.scarab.util.IteratorWithSize;
0135: import org.tigris.scarab.util.Log;
0136: import org.tigris.scarab.util.ScarabConstants;
0137: import org.tigris.scarab.util.ScarabException;
0138: import org.tigris.scarab.util.ScarabLink;
0139: import org.tigris.scarab.util.ScarabPaginatedList;
0140: import org.tigris.scarab.util.SimpleSkipFiltering;
0141: import org.tigris.scarab.util.SnippetRenderer;
0142: import org.tigris.scarab.util.SubsetIteratorWithSize;
0143: import org.tigris.scarab.util.WindowIterator;
0144: import org.tigris.scarab.util.word.ComplexQueryException;
0145: import org.tigris.scarab.util.word.IssueSearch;
0146: import org.tigris.scarab.util.word.IssueSearchFactory;
0147: import org.tigris.scarab.util.word.MaxConcurrentSearchException;
0148: import org.tigris.scarab.util.word.QueryResult;
0149: import org.tigris.scarab.util.word.SearchIndex;
0150: import org.tigris.scarab.workflow.TransitionNode;
0151: import org.tigris.scarab.workflow.Workflow;
0152:
0153: /**
0154: * This class is used by the Scarab API
0155: */
0156: public class ScarabRequestTool implements ApplicationTool, Recyclable {
0157: private static final String TIME_ZONE = Turbine.getConfiguration()
0158: .getString("scarab.timezone", "");
0159:
0160: /**
0161: * The disposed flag.
0162: */
0163: private boolean disposed;
0164:
0165: /** the object containing request specific data */
0166: private RunData data;
0167:
0168: /**
0169: * A User object for use within the Scarab API.
0170: */
0171: private ScarabUser user = null;
0172:
0173: /**
0174: * A Issue object for use within the Scarab API.
0175: */
0176: private Issue issue = null;
0177:
0178: /**
0179: * The <code>Alert!</code> message for this request.
0180: */
0181: private Object alert = null;
0182:
0183: /**
0184: * A Attribute object for use within the Scarab API.
0185: */
0186: private Attribute attribute = null;
0187:
0188: /**
0189: * A Attachment object for use within the Scarab API.
0190: */
0191: private Attachment attachment = null;
0192:
0193: /**
0194: * A Depend object for use within the Scarab API.
0195: */
0196: private Depend depend = null;
0197:
0198: /**
0199: * A Query object for use within the Scarab API.
0200: */
0201: private Query query = null;
0202:
0203: /**
0204: * An IssueTemplateInfo object for use within the Scarab API.
0205: */
0206: private IssueTemplateInfo templateInfo = null;
0207:
0208: /**
0209: * An IssueType object for use within the Scarab API.
0210: */
0211: private IssueType issueType = null;
0212:
0213: /**
0214: * The issue that is currently being entered.
0215: */
0216: private Issue reportingIssue = null;
0217:
0218: /**
0219: * A Module object
0220: */
0221: private Module module = null;
0222:
0223: /**
0224: * A AttributeOption object for use within the Scarab API.
0225: */
0226: private AttributeOption attributeOption = null;
0227:
0228: /**
0229: * A ROptionOption
0230: */
0231: private ROptionOption roo = null;
0232:
0233: /**
0234: * A ParentChildAttributeOption
0235: */
0236: private ParentChildAttributeOption pcao = null;
0237:
0238: /**
0239: * IssueSearch object for performing queries
0240: */
0241: private IssueSearch issueSearch = null;
0242:
0243: /**
0244: * keep track if the columns were reduced to avoid db limits
0245: */
0246: int initialIssueListColumnsSize = 0;
0247:
0248: /**
0249: * cache list so that we always return the same object for
0250: * all invocations within a single request
0251: */
0252: List issueListColumns = null;
0253:
0254: /**
0255: * A ReportGenerator
0256: */
0257: private ReportBridge reportGenerator = null;
0258:
0259: private int nbrPages = 0;
0260: private int prevPage = 0;
0261: private int nextPage = 0;
0262: private String cachedNextIssueId;
0263: private String cachedPrevIssueId;
0264:
0265: /* messages usually set in actions */
0266: private Object confirmMessage;
0267: private Object infoMessage;
0268: private Object alertMessage;
0269:
0270: /** The time zone that will be used when formatting dates */
0271: private final TimeZone timezone;
0272:
0273: Map attributeTypes = new HashMap();
0274:
0275: /**
0276: * Constructor does initialization stuff
0277: */
0278: public ScarabRequestTool() {
0279: recycle();
0280: timezone = TIME_ZONE == null ? null : TimeZone
0281: .getTimeZone(TIME_ZONE);
0282: }
0283:
0284: /**
0285: * This method expects to get a RunData object
0286: */
0287: public void init(Object data) {
0288: this .data = (RunData) data;
0289:
0290: }
0291:
0292: /**
0293: * nulls out the issue and user objects
0294: */
0295: public void refresh() {
0296: user = null;
0297: issue = null;
0298: attribute = null;
0299: attachment = null;
0300: depend = null;
0301: query = null;
0302: templateInfo = null;
0303: issueType = null;
0304: reportingIssue = null;
0305: module = null;
0306: attributeOption = null;
0307: roo = null;
0308: pcao = null;
0309: attributeTypes = new HashMap();
0310: if (issueSearch != null) {
0311: // This must _always_ be called by dispose()
0312: Log.get().debug(
0313: "IssueSearch object is disposed of properly.");
0314: issueSearch.close();
0315: IssueSearchFactory.INSTANCE.notifyDone();
0316: issueSearch = null;
0317: }
0318: issueListColumns = null;
0319: initialIssueListColumnsSize = 0;
0320: reportGenerator = null;
0321: nbrPages = 0;
0322: prevPage = 0;
0323: nextPage = 0;
0324: confirmMessage = null;
0325: infoMessage = null;
0326: alertMessage = null;
0327: cachedPrevIssueId = null;
0328: cachedNextIssueId = null;
0329: }
0330:
0331: /**
0332: * Sets the <code>Alert!</code> message for this request.
0333: *
0334: * @param message The alert message to set.
0335: */
0336: public void setAlert(Object message) {
0337: this .alert = message;
0338: }
0339:
0340: /**
0341: * Retrieves any <code>Alert!</code> message which has been set.
0342: *
0343: * @return The alert message.
0344: */
0345: public Object getAlert() {
0346: return alert;
0347: }
0348:
0349: /**
0350: * A Attachment object for use within the Scarab API
0351: */
0352: public void setAttachment(Attachment attachment) {
0353: this .attachment = attachment;
0354: }
0355:
0356: /**
0357: * A Attribute object for use within the Scarab API.
0358: */
0359: public void setAttribute(Attribute attribute) {
0360: this .attribute = attribute;
0361: }
0362:
0363: /**
0364: * A Depend object for use within the Scarab API.
0365: */
0366: public void setDepend(Depend depend) {
0367: this .depend = depend;
0368: }
0369:
0370: /**
0371: * A Query object for use within the Scarab API.
0372: */
0373: public void setQuery(Query query) {
0374: this .query = query;
0375: }
0376:
0377: /**
0378: * Get the intake tool.
0379: */
0380: private IntakeTool getIntakeTool() {
0381: return (IntakeTool) org.apache.turbine.modules.Module
0382: .getTemplateContext(data).get(
0383: ScarabConstants.INTAKE_TOOL);
0384: }
0385:
0386: /**
0387: * Gets an instance of a ROptionOption from this tool.
0388: * if it is null it will return a new instance of an
0389: * empty ROptionOption and set it within this tool.
0390: */
0391: public ROptionOption getROptionOption() {
0392: if (roo == null) {
0393: roo = ROptionOption.getInstance();
0394: }
0395: return roo;
0396: }
0397:
0398: /**
0399: * Sets an instance of a ROptionOption
0400: */
0401: public void setROptionOption(ROptionOption roo) {
0402: this .roo = roo;
0403: }
0404:
0405: /**
0406: * A IssueTemplateInfo object for use within the Scarab API.
0407: */
0408: public void setIssueTemplateInfo(IssueTemplateInfo templateInfo) {
0409: this .templateInfo = templateInfo;
0410: }
0411:
0412: /**
0413: * A IssueType object for use within the Scarab API.
0414: */
0415: public void setIssueType(IssueType issuetype) {
0416: this .issueType = issuetype;
0417: }
0418:
0419: /**
0420: * Gets an instance of a ParentChildAttributeOption from this tool.
0421: * if it is null it will return a new instance of an
0422: * empty ParentChildAttributeOption and set it within this tool.
0423: */
0424: public ParentChildAttributeOption getParentChildAttributeOption() {
0425: if (pcao == null) {
0426: pcao = ParentChildAttributeOption.getInstance();
0427: }
0428: return pcao;
0429: }
0430:
0431: /**
0432: * Sets an instance of a ParentChildAttributeOption
0433: */
0434: public void setParentChildAttributeOption(
0435: ParentChildAttributeOption roo) {
0436: this .pcao = roo;
0437: }
0438:
0439: /**
0440: * A Attribute object for use within the Scarab API.
0441: */
0442: public void setAttributeOption(AttributeOption option) {
0443: this .attributeOption = option;
0444: }
0445:
0446: /**
0447: * A Attribute object for use within the Scarab API.
0448: */
0449: public AttributeOption getAttributeOption() throws Exception {
0450: if (attributeOption == null) {
0451: String optId = getIntakeTool().get("AttributeOption",
0452: IntakeTool.DEFAULT_KEY).get("OptionId").toString();
0453: if (optId == null || optId.length() == 0) {
0454: attributeOption = AttributeOptionManager.getInstance();
0455: } else {
0456: attributeOption = AttributeOptionManager
0457: .getInstance(new Integer(optId));
0458: }
0459: }
0460: return attributeOption;
0461: }
0462:
0463: /**
0464: * A <code>User</code> object for use within the Scarab API,
0465: * generally <i>not</i> the user who is logged in.
0466: */
0467: public void setUser(ScarabUser user) {
0468: this .user = user;
0469: }
0470:
0471: /**
0472: * A <code>User</code> object for use within the Scarab API. This
0473: * is the result of whatever was set with <code>setUser()</code>
0474: * (generally <i>not</i> the user who is logged in). It can
0475: * return <code>null</code> if <code>setUser()</code> has not been
0476: * previously called. If you would like to get the currently
0477: * logged in <code>User</code>, retrieve that from the
0478: * data.getUser() method.
0479: *
0480: * @return A user used during this request.
0481: */
0482: public ScarabUser getUser() {
0483: return user;
0484: }
0485:
0486: /**
0487: * retrieves the user from the current request.
0488: * If the current request has no explicit user in it's data section,
0489: * retrieve the current user from the current session.
0490: * @return
0491: */
0492: public ScarabUser getCurrentUser() {
0493: ScarabUser result = (ScarabUser) data.getUser();
0494: if (user == null) {
0495: result = (ScarabUser) data.getUserFromSession();
0496: }
0497: return result;
0498: }
0499:
0500: /**
0501: * Return a specific User by ID from within the system.
0502: * You can pass in either a Integer or something that
0503: * will resolve to a String object as id.toString() is
0504: * called on everything that isn't a Integer.
0505: */
0506: public ScarabUser getUser(Object id) throws Exception {
0507: if (id == null) {
0508: return null;
0509: }
0510: ScarabUser su = null;
0511: try {
0512: Integer pk = null;
0513: if (id instanceof Integer) {
0514: pk = (Integer) id;
0515: } else {
0516: pk = new Integer(id.toString());
0517: }
0518: su = ScarabUserManager.getInstance(pk);
0519: } catch (Exception e) {
0520: // Logged at debug level, as a null user is interpreted
0521: // as an invalid user id
0522: Log.get().debug(
0523: "User with user id " + id + " could not be found,",
0524: e);
0525: }
0526: return su;
0527: }
0528:
0529: /**
0530: * Return a specific User by username.
0531: */
0532: public ScarabUser getUserByUserName(String username)
0533: throws Exception {
0534: ScarabUser su = null;
0535: try {
0536: su = ScarabUserManager.getInstance(username);
0537: } catch (Exception e) {
0538: // Logged at debug level, as a null user is interpreted
0539: // as an invalid username
0540: Log.get().debug(
0541: "User, " + username + " could not be found,", e);
0542: }
0543: return su;
0544: }
0545:
0546: /**
0547: * @return An {@link org.tigris.scarab.om.Attribute} object
0548: * (possibly "blank", but never <code>null</code>).
0549: */
0550: public Attribute getAttribute() throws Exception {
0551: try {
0552: if (attribute == null) {
0553: String attId = getIntakeTool().get("Attribute",
0554: IntakeTool.DEFAULT_KEY).get("Id").toString();
0555: if (attId == null || attId.length() == 0) {
0556: attId = data.getParameters().getString("attId");
0557: if (attId == null || attId.length() == 0) {
0558: attribute = AttributeManager.getInstance();
0559: } else {
0560: attribute = AttributeManager
0561: .getInstance(new Integer(attId));
0562: }
0563: } else {
0564: attribute = AttributeManager
0565: .getInstance(new Integer(attId));
0566: }
0567: }
0568: } catch (Exception e) {
0569: e.printStackTrace();
0570: }
0571: return attribute;
0572: }
0573:
0574: /**
0575: * A Attribute object for use within the Scarab API.
0576: */
0577: public Attribute getAttribute(Integer pk) throws Exception {
0578: Attribute attr = null;
0579: try {
0580: attr = AttributeManager.getInstance(pk);
0581: } catch (Exception e) {
0582: e.printStackTrace();
0583: }
0584: this .attribute = attr;
0585: return attr;
0586: }
0587:
0588: /**
0589: * A Attribute object for use within the Scarab API.
0590: */
0591: public AttributeOption getAttributeOption(Integer pk)
0592: throws Exception {
0593: try {
0594: attributeOption = AttributeOptionManager.getInstance(pk);
0595: } catch (Exception e) {
0596: e.printStackTrace();
0597: }
0598: return attributeOption;
0599: }
0600:
0601: public AttributeOption getAttributeOption(String key)
0602: throws Exception {
0603: return getAttributeOption(new Integer(key));
0604: }
0605:
0606: /**
0607: * First attempts to get the RModuleUserAttributes from the user.
0608: * If it is empty, then it will try to get the defaults from the module.
0609: * If anything fails, it will return an empty list.
0610: */
0611: public List getRModuleUserAttributes() {
0612: ScarabUser user = (ScarabUser) data.getUser();
0613:
0614: if (issueListColumns == null) {
0615: ScarabLocalizationTool l10n = getLocalizationTool();
0616: ScarabToolManager toolManager = new ScarabToolManager(l10n);
0617: issueListColumns = toolManager.getRModuleUserAttributes(
0618: user, user.getCurrentModule(), issueType);
0619: if (issueListColumns == null) {
0620: issueListColumns = Collections.EMPTY_LIST;
0621: }
0622: initialIssueListColumnsSize = issueListColumns.size();
0623: }
0624:
0625: // DEP: Not sure about this initial list stuff, or if we need it..
0626: if (initialIssueListColumnsSize > issueListColumns.size()) {
0627: TemplateContext context = (TemplateContext) data
0628: .getTemp(Turbine.CONTEXT);
0629: context.put("columnLimitExceeded", Boolean.TRUE);
0630: }
0631: return issueListColumns;
0632: }
0633:
0634: public List getValidIssueListAttributes() {
0635: List result = getIssueListAttributes(false, true);
0636: return result;
0637: }
0638:
0639: public List getAllValidIssueListAttributes() {
0640: List result = getIssueListAttributes(true, false);
0641: return result;
0642: }
0643:
0644: public List getIssueListAttributes(boolean validOnly,
0645: boolean commonOnly) {
0646: ScarabUser user = (ScarabUser) data.getUser();
0647: List result = null;
0648: try {
0649: MITList currentList = user.getCurrentMITList();
0650: if (currentList != null) {
0651: result = currentList.getAttributes(validOnly,
0652: commonOnly);
0653: }
0654: } catch (Exception e) {
0655: Log.get().error("Could not get list attributes", e);
0656: }
0657: if (result == null) {
0658: result = new ArrayList();
0659: }
0660: return result;
0661: }
0662:
0663: /**
0664: * A Query object for use within the Scarab API.
0665: */
0666: public Query getQuery() throws Exception {
0667: try {
0668: if (query == null) {
0669: String queryId = data.getParameters().getString(
0670: "queryId");
0671: if (queryId == null || queryId.length() == 0) {
0672: query = Query.getInstance();
0673: } else {
0674: query = QueryManager.getInstance(new NumberKey(
0675: queryId), false);
0676: }
0677: }
0678: } catch (Exception e) {
0679: e.printStackTrace();
0680: }
0681: return query;
0682: }
0683:
0684: /**
0685: * A IssueTemplateInfo object for use within the Scarab API.
0686: */
0687: public IssueTemplateInfo getIssueTemplateInfo() throws Exception {
0688: try {
0689: if (templateInfo == null) {
0690: String templateId = data.getParameters().getString(
0691: "templateId");
0692:
0693: if (templateId == null || templateId.length() == 0) {
0694: templateInfo = IssueTemplateInfo.getInstance();
0695: } else {
0696: templateInfo = IssueTemplateInfoManager
0697: .getInstance(new NumberKey(templateId),
0698: false);
0699: }
0700: }
0701: } catch (Exception e) {
0702: e.printStackTrace();
0703: }
0704: return templateInfo;
0705: }
0706:
0707: /**
0708: * An Enter issue template.
0709: */
0710: public Issue getIssueTemplate() throws Exception {
0711: Issue template = null;
0712: String templateId = data.getParameters()
0713: .getString("templateId");
0714: try {
0715: if (templateId == null || templateId.length() == 0) {
0716: IssueType issueType = getCurrentIssueType();
0717: Integer templateID = issueType.getTemplateId();
0718: if (templateID.intValue() != 0) {
0719: IssueType finalIssueType = getIssueType(templateID
0720: .toString());
0721: template = getCurrentModule().getNewIssue(
0722: finalIssueType);
0723: }
0724: } else {
0725: template = IssueManager.getInstance(new NumberKey(
0726: templateId), false);
0727: }
0728: } catch (Exception e) {
0729: e.printStackTrace();
0730: }
0731: return template;
0732: }
0733:
0734: /**
0735: * An Enter issue template.
0736: */
0737: public Issue getIssueTemplate(String templateId) throws Exception {
0738: Issue template = null;
0739: try {
0740: if (templateId == null || templateId.length() == 0) {
0741: setAlertMessage(L10NKeySet.NoTemplateId);
0742: } else {
0743: template = IssueManager.getInstance(new NumberKey(
0744: templateId), false);
0745: }
0746: } catch (Exception e) {
0747: e.printStackTrace();
0748: }
0749: return template;
0750: }
0751:
0752: /**
0753: * A Depend object for use within the Scarab API.
0754: */
0755: public Depend getDepend() throws Exception {
0756: try {
0757: if (depend == null) {
0758: String dependId = getIntakeTool().get("Depend",
0759: IntakeTool.DEFAULT_KEY).get("Id").toString();
0760: if (dependId == null || dependId.length() == 0) {
0761: depend = DependManager.getInstance();
0762: } else {
0763: depend = DependManager.getInstance(new NumberKey(
0764: dependId), false);
0765: }
0766: }
0767: } catch (Exception e) {
0768: e.printStackTrace();
0769: }
0770: return depend;
0771: }
0772:
0773: /**
0774: * A Attachment object for use within the Scarab API.
0775: */
0776: public Attachment getAttachment() throws Exception {
0777: try {
0778: if (attachment == null) {
0779: Group att = getIntakeTool().get("Attachment",
0780: IntakeTool.DEFAULT_KEY, false);
0781: if (att != null) {
0782: String attId = att.get("Id").toString();
0783: if (attId == null || attId.length() == 0) {
0784: attachment = new Attachment();
0785: } else {
0786: attachment = AttachmentManager.getInstance(
0787: new NumberKey(attId), false);
0788: }
0789: } else {
0790: attachment = new Attachment();
0791: }
0792: }
0793: } catch (Exception e) {
0794: e.printStackTrace();
0795: throw e; //EXCEPTION
0796: }
0797: return attachment;
0798: }
0799:
0800: /**
0801: * A AttributeGroup object for use within the Scarab API.
0802: */
0803: public AttributeGroup getAttributeGroup() throws Exception {
0804: AttributeGroup group = null;
0805: try {
0806: String attGroupId = getIntakeTool().get("AttributeGroup",
0807: IntakeTool.DEFAULT_KEY).get("AttributeGroupId")
0808: .toString();
0809: if (attGroupId == null || attGroupId.length() == 0) {
0810: group = new AttributeGroup();
0811: } else {
0812: group = AttributeGroupManager.getInstance(
0813: new NumberKey(attGroupId), false);
0814: }
0815: } catch (Exception e) {
0816: e.printStackTrace();
0817: }
0818: return group;
0819:
0820: }
0821:
0822: /**
0823: * Get a AttributeGroup object.
0824: */
0825: public AttributeGroup getAttributeGroup(String key) {
0826: AttributeGroup group = null;
0827: try {
0828: group = AttributeGroupManager.getInstance(
0829: new NumberKey(key), false);
0830: } catch (Exception e) {
0831: e.printStackTrace();
0832: }
0833: return group;
0834: }
0835:
0836: /**
0837: * Get a specific issue type by key value. Returns null if
0838: * the Issue Type could not be found
0839: *
0840: * @param key a <code>String</code> value
0841: * @return a <code>IssueType</code> value
0842: */
0843: public IssueType getIssueType(String key) {
0844: IssueType issueType = null;
0845: try {
0846: issueType = IssueTypeManager.getInstance(
0847: new NumberKey(key), false);
0848: } catch (Exception e) {
0849: // Swallow me!
0850: }
0851: return issueType;
0852: }
0853:
0854: /**
0855: * Get an issue type object.
0856: */
0857: public IssueType getIssueType() throws Exception {
0858: if (issueType == null) {
0859: String key = data.getParameters().getString("issuetypeid");
0860: if (key == null) {
0861: // get new issue type
0862: issueType = new IssueType();
0863: } else {
0864: try {
0865: issueType = IssueTypeManager.getInstance(
0866: new NumberKey(key), false);
0867: } catch (Exception e) {
0868: issueType = new IssueType();
0869: }
0870: }
0871: }
0872: return issueType;
0873: }
0874:
0875: /**
0876: * Gets a new instance of AttributeValue
0877: */
0878: public AttributeValue getNewAttributeValue(Attribute attribute,
0879: Issue issue) throws Exception {
0880:
0881: return AttributeValue.getNewInstance(
0882: attribute.getAttributeId(), issue);
0883: }
0884:
0885: /**
0886: * Get an RModuleAttribute object.
0887: *
0888: * @return a <code>Module</code> value
0889: */
0890: public RModuleAttribute getRModuleAttribute() throws Exception {
0891: RModuleAttribute rma = null;
0892: try {
0893: ComboKey rModAttId = (ComboKey) getIntakeTool().get(
0894: "RModuleAttribute", IntakeTool.DEFAULT_KEY).get(
0895: "Id").getValue();
0896: if (rModAttId == null) {
0897: Integer attId = (Integer) getIntakeTool().get(
0898: "Attribute", IntakeTool.DEFAULT_KEY).get("Id")
0899: .getValue();
0900: Module currentModule = getCurrentModule();
0901: if (attId != null && currentModule != null) {
0902: SimpleKey[] nka = {
0903: SimpleKey.keyFor(attId),
0904: SimpleKey.keyFor(currentModule
0905: .getModuleId()) };
0906: rma = RModuleAttributeManager.getInstance(
0907: new ComboKey(nka), false);
0908: } else {
0909: rma = new RModuleAttribute();
0910: }
0911: } else {
0912: rma = RModuleAttributeManager.getInstance(rModAttId,
0913: false);
0914: }
0915: } catch (Exception e) {
0916: e.printStackTrace();
0917: }
0918: return rma;
0919: }
0920:
0921: /**
0922: * A Module object for use within the Scarab API.
0923: */
0924: public void setModule(Module module) {
0925: this .module = module;
0926: }
0927:
0928: /**
0929: * Get an Module object.
0930: *
0931: * @return a <code>Module</code> value
0932: */
0933: public Module getModule() throws Exception {
0934: try {
0935: String modId = getIntakeTool().get("Module",
0936: IntakeTool.DEFAULT_KEY).get("Id").toString();
0937: if (modId == null || modId.length() == 0) {
0938: module = ModuleManager.getInstance();
0939: } else {
0940: module = ModuleManager.getInstance(new Integer(modId));
0941: }
0942: } catch (Exception e) {
0943: e.printStackTrace();
0944: }
0945: return module;
0946: }
0947:
0948: /**
0949: * Get a specific module by key value. Returns null if
0950: * the Module could not be found
0951: *
0952: * @param key a <code>String</code> value
0953: * @return a <code>Module</code> value
0954: */
0955: public Module getModule(String key) {
0956: Module me = null;
0957: if (key != null && key.length() > 0) {
0958: try {
0959: me = ModuleManager.getInstance(new Integer(key));
0960: } catch (Exception e) {
0961: Log.get().info(
0962: "[ScarabRequestTool] Unable to retrieve Module: "
0963: + key, e);
0964: }
0965: }
0966: return me;
0967: }
0968:
0969: /**
0970: * Gets the Module associated with the information
0971: * passed around in the query string. Returns null if
0972: * the Module could not be found.
0973: */
0974: public Module getCurrentModule() {
0975: ScarabUser user = (ScarabUser) data.getUser();
0976: Module currentModule = null;
0977: if (user != null) {
0978: currentModule = user.getCurrentModule();
0979: }
0980:
0981: return currentModule;
0982: }
0983:
0984: /**
0985: * Gets the IssueType associated with the information
0986: * passed around in the query string.
0987: */
0988: public IssueType getCurrentIssueType() throws Exception {
0989: ScarabUser user = (ScarabUser) data.getUser();
0990: IssueType curit = user.getCurrentIssueType();
0991: if (curit == null) {
0992: Integer curitID = data.getParameters().getInteger(
0993: ScarabConstants.CURRENT_ISSUE_TYPE);
0994: if (curitID.intValue() != 0) {
0995: curit = IssueTypeManager.getInstance(curitID);
0996: }
0997: }
0998: return curit;
0999: }
1000:
1001: public void setCurrentIssueType(IssueType type) {
1002: ScarabUser user = (ScarabUser) data.getUser();
1003: if (user != null) {
1004: user.setCurrentIssueType(type);
1005: }
1006: }
1007:
1008: /**
1009: * Looks at the current RModuleIssueType and if it is null,
1010: * returns the users home page. If it is not null, and is
1011: * dedupe, returns Wizard1...else Wizard3.
1012: */
1013: public String getNextEntryTemplate(IssueType issueType) {
1014: RModuleIssueType rmit = null;
1015: String nextTemplate = null;
1016: try {
1017: Module module = getCurrentModule();
1018: if (module == null) {
1019: nextTemplate = ((ScarabUser) data.getUser())
1020: .getHomePage();
1021: setAlertMessage(L10NKeySet.ModuleIssueTypeRequiredToEnterIssue);
1022: } else {
1023: rmit = module.getRModuleIssueType(issueType);
1024: if (rmit == null) {
1025: nextTemplate = ((ScarabUser) data.getUser())
1026: .getHomePage();
1027: setAlertMessage(L10NKeySet.ModuleIssueTypeRequiredToEnterIssue);
1028: } else if (rmit.getDedupe()
1029: && !module.getDedupeGroupsWithAttributes(
1030: issueType).isEmpty()) {
1031: nextTemplate = "entry,Wizard1.vm";
1032: } else {
1033: nextTemplate = "entry,Wizard3.vm";
1034: }
1035: }
1036: } catch (Exception e) {
1037: // system would be messed up, if we are here. Punt
1038: nextTemplate = "Index.vm";
1039: setAlertMessage(L10NKeySet.CannotDetermineIssueEntryTemplate);
1040: Log.get().error("CannotDetermineIssueEntryTemplate", e);
1041: }
1042: return nextTemplate;
1043: }
1044:
1045: /**
1046: * Returns name of current template
1047: */
1048: public String getCurrentTemplate() {
1049: String result = data.getTarget().replace('/', ',');
1050: return result;
1051: }
1052:
1053: /**
1054: * The issue that is currently being entered.
1055: *
1056: * @return an <code>Issue</code> value
1057: */
1058: public Issue getReportingIssue() throws Exception {
1059: if (reportingIssue == null) {
1060: String key = data.getParameters().getString(
1061: ScarabConstants.REPORTING_ISSUE);
1062:
1063: if (key == null) {
1064: getNewReportingIssue();
1065: } else {
1066: reportingIssue = ((ScarabUser) data.getUser())
1067: .getReportingIssue(key);
1068:
1069: // if reportingIssue is still null, the parameter must have
1070: // been stale, just get a new issue
1071: if (reportingIssue == null) {
1072: getNewReportingIssue();
1073: }
1074: }
1075: }
1076: return reportingIssue;
1077: }
1078:
1079: private void getNewReportingIssue() throws Exception {
1080: reportingIssue = getCurrentModule().getNewIssue(
1081: getCurrentIssueType());
1082: String key = ((ScarabUser) data.getUser())
1083: .setReportingIssue(reportingIssue);
1084: data.getParameters().add(ScarabConstants.REPORTING_ISSUE, key);
1085: }
1086:
1087: public void setReportingIssue(Issue issue) {
1088: reportingIssue = issue;
1089: }
1090:
1091: /**
1092: * Sets the current Module
1093: */
1094: public void setCurrentModule(Module me) {
1095: ScarabUser user = (ScarabUser) data.getUser();
1096: if (user != null) {
1097: user.setCurrentModule(me);
1098: }
1099: }
1100:
1101: /**
1102: * A Issue object for use within the Scarab API.
1103: */
1104: public void setIssue(Issue issue) {
1105: this .issue = issue;
1106: }
1107:
1108: /**
1109: * Get an Issue object from unique id given either as an intake
1110: * field or a request parameter keyed with "id".
1111: *
1112: * @return a <code>Issue</code> value
1113: */
1114: public Issue getIssue() throws Exception {
1115: if (issue == null) {
1116: String issueId = null;
1117: Group issueGroup = getIntakeTool().get("Issue",
1118: IntakeTool.DEFAULT_KEY, false);
1119: if (issueGroup != null) {
1120: issueId = issueGroup.get("Id").toString();
1121: } else {
1122: issueId = data.getParameters().getString("id");
1123: }
1124: if (issueId != null && issueId.length() > 0) {
1125: issue = getIssue(issueId);
1126: }
1127: }
1128: return issue;
1129: }
1130:
1131: /**
1132: * Takes unique id and returns issue.
1133: * @param id
1134: * @return
1135: */
1136: public Issue getIssue(String id) {
1137: Issue issue = null;
1138: if (id == null || id.length() == 0) {
1139: setInfoMessage(L10NKeySet.EnterId);
1140: } else {
1141: try {
1142: issue = IssueManager.getIssueById(id,
1143: getCurrentModule().getCode());
1144: if (issue != null && issue.getDeleted()) {
1145: issue = null;
1146: }
1147: } catch (Exception e) {
1148: setAlertMessage(L10NKeySet.InvalidId);
1149: }
1150: }
1151: return issue;
1152: }
1153:
1154: /**
1155: * Returns an issue given its ID, even if it's been
1156: * deleted or moved.
1157: * @param id
1158: * @return
1159: */
1160: public Issue getIssueIncludingDeleted(String id) {
1161: Issue issue = null;
1162: issue = IssueManager.getIssueById(id);
1163: return issue;
1164: }
1165:
1166: /**
1167: * The id may only be the issue's primary key.
1168: *
1169: * @param key a <code>String</code> value
1170: * @return a <code>Issue</code> value
1171: */
1172: public Issue getIssueByPk(String key) {
1173: Issue issue = null;
1174: try {
1175: issue = IssueManager.getInstance(new Long(key));
1176: } catch (Exception e) {
1177: setAlertMessage(L10NKeySet.InvalidIssueId);
1178: }
1179: return issue;
1180: }
1181:
1182: /**
1183: * Get a list of Issue objects.
1184: *
1185: * @return a <code>Issue</code> value
1186: */
1187: public List getIssues() throws Exception {
1188: List issues = null;
1189:
1190: Group issueGroup = getIntakeTool().get("Issue",
1191: IntakeTool.DEFAULT_KEY, false);
1192: if (issueGroup != null) {
1193: Long[] issueIds = (Long[]) issueGroup.get("Ids").getValue();
1194: if (issueIds != null) {
1195: issues = getIssues(Arrays.asList(issueIds));
1196: }
1197: } else {
1198: String[] paramIssueIds = data.getParameters().getStrings(
1199: "issue_ids");
1200: if (paramIssueIds != null) {
1201: issues = getIssues(Arrays.asList(paramIssueIds));
1202: }
1203: }
1204: if (issues == null) {
1205: issues = Collections.EMPTY_LIST;
1206: }
1207: return issues;
1208: }
1209:
1210: /**
1211: * Get a list of Issue objects from a list of issue IDs. The list
1212: * can contain Strings or Integers, but all IDs must be of the same type
1213: * (String or Integer).
1214: *
1215: * @param issueIds a <code>List</code> value
1216: * @return a <code>List</code> value
1217: * @exception Exception if an error occurs
1218: */
1219: public List getIssues(List issueIds) throws Exception {
1220: List issues = null;
1221: StringBuffer invalidIds = null;
1222: if (issueIds == null || issueIds.isEmpty()) {
1223: issues = Collections.EMPTY_LIST;
1224: } else {
1225: if (issueIds.get(0) instanceof String) {
1226: issues = new ArrayList(issueIds.size());
1227: Iterator i = issueIds.iterator();
1228: while (i.hasNext()) {
1229: String id = (String) i.next();
1230: Issue issue = getIssue(id);
1231: if (issue == null) {
1232: if (invalidIds == null) {
1233: invalidIds = new StringBuffer(id);
1234: } else {
1235: invalidIds.append(' ').append(id);
1236: }
1237: } else {
1238: issues.add(issue);
1239: }
1240: }
1241: if (invalidIds != null) {
1242: setAlertMessage(getLocalizationTool().format(
1243: "SomeIssueIdsNotValid",
1244: invalidIds.toString()));
1245: }
1246: } else if (issueIds.get(0) instanceof Long) {
1247: issues = new ArrayList(issueIds.size());
1248: Iterator i = issueIds.iterator();
1249: while (i.hasNext()) {
1250: Issue issue = IssueManager.getInstance((Long) i
1251: .next());
1252: if (issue == null) {
1253: setAlertMessage(L10NKeySet.SomeIssuePKsNotValid);
1254: } else {
1255: issues.add(issue);
1256: }
1257: }
1258: } else {
1259: throw new IllegalArgumentException(
1260: "issue ids must be Strings or Longs, not "
1261: + issueIds.get(0).getClass().getName()); //EXCEPTION
1262: }
1263: }
1264: return issues;
1265: }
1266:
1267: /**
1268: * retrieve an attribute value from the current HttpSession.
1269: * Throws a ScarabException, if no HttpSession is available.
1270: * Returns empty String ("") if the Attribute is not available;
1271: * @param key
1272: * @return
1273: * @throws ScarabException
1274: */
1275: public Object getSessionAttribute(String key)
1276: throws ScarabException {
1277: HttpSession session = data.getSession();
1278: Object value;
1279: if (session == null) {
1280: L10NMessage msg = new L10NMessage(
1281: L10NKeySet.NoSessionAvailable);
1282: throw new ScarabException(msg);
1283: }
1284: value = session.getAttribute(key);
1285: return value;
1286: }
1287:
1288: /**
1289: * Check whether the current session has an attribute of given key.
1290: * If there is no active session available, throw a scarabException.
1291: * returns true, if attribute exists, otherwise returns false.
1292: */
1293: public boolean hasSessionAttribute(String key)
1294: throws ScarabException {
1295: HttpSession session = data.getSession();
1296: Object value;
1297: if (session == null) {
1298: L10NMessage msg = new L10NMessage(
1299: L10NKeySet.NoSessionAvailable);
1300: throw new ScarabException(msg);
1301: }
1302: value = session.getAttribute(key);
1303: return value != null;
1304: }
1305:
1306: /**
1307: * Place an attribute value into the current HttpSession.
1308: * Throws a ScarabException, if no HttpSession is available.
1309: * @param key
1310: * @param value
1311: * @throws ScarabException
1312: */
1313: public boolean setSessionAttribute(String key, Object value)
1314: throws ScarabException {
1315: HttpSession session = data.getSession();
1316: if (session == null) {
1317: L10NMessage msg = new L10NMessage(
1318: L10NKeySet.NoSessionAvailable);
1319: throw new ScarabException(msg);
1320: }
1321: session.setAttribute(key, value);
1322: return true;
1323: }
1324:
1325: /**
1326: * Get all scopes.
1327: */
1328: public List getScopes() throws Exception {
1329: return ScopePeer.getAllScopes();
1330: }
1331:
1332: /**
1333: * Get all frequencies.
1334: */
1335: public List getFrequencies() throws Exception {
1336: return FrequencyPeer.getFrequencies();
1337: }
1338:
1339: /**
1340: * Generates link to Issue List page, re-running stored query.
1341: */
1342: public String getExecuteLink(String link, Query query) {
1343: // query.getValue() begins with a &
1344: link = link + "?action=Search&eventSubmit_doSearch=Search"
1345: + "&pagenum=1" + query.getValue();
1346:
1347: Long listId = query.getListId();
1348: if (listId != null) {
1349: link += '&' + ScarabConstants.CURRENT_MITLIST_ID + '='
1350: + listId;
1351: } else {
1352: link += '&' + ScarabConstants.REMOVE_CURRENT_MITLIST_QKEY
1353: + "=true";
1354: }
1355: return link;
1356: }
1357:
1358: /**
1359: * Generates link to the Query Detail page.
1360: */
1361: public String getEditLink(String link, Query query) {
1362: // query.getValue() begins with a &
1363: link = link + "?queryId=" + query.getQueryId() + "&refine=true"
1364: + "&action=Search&eventSubmit_doPreparequery=foo"
1365: + query.getValue();
1366:
1367: Long listId = query.getListId();
1368: if (listId != null) {
1369: link += '&' + ScarabConstants.CURRENT_MITLIST_ID + '='
1370: + listId;
1371: } else {
1372: link += '&' + ScarabConstants.REMOVE_CURRENT_MITLIST_QKEY
1373: + "=true";
1374: }
1375: return link;
1376: }
1377:
1378: public Intake getConditionalIntake(String parameter)
1379: throws Exception {
1380: Intake intake = null;
1381: String param = data.getParameters().getString(parameter);
1382: if (param == null) {
1383: intake = getIntakeTool();
1384: } else {
1385: intake = new Intake();
1386: StringValueParser parser = new StringValueParser();
1387: parser.parse(param, '&', '=', true);
1388: intake.init(parser);
1389: }
1390:
1391: return intake;
1392: }
1393:
1394: /**
1395: * Get a new IssueSearch object.
1396: *
1397: * @return a <code>Issue</code> value
1398: */
1399: public IssueSearch getNewSearch() throws Exception,
1400: MaxConcurrentSearchException {
1401: if (issueSearch == null) {
1402: ScarabUser user = (ScarabUser) data.getUser();
1403: MITList mitList = user.getCurrentMITList();
1404: if (mitList == null) {
1405: setAlertMessage(L10NKeySet.NoIssueTypeList);
1406: Log
1407: .get()
1408: .warn(
1409: "Attempted to create a new IssueSearch and "
1410: + " issue types had not been selected.");
1411: } else {
1412: issueSearch = IssueSearchFactory.INSTANCE.getInstance(
1413: mitList, user);
1414: issueSearch.setLocale(getLocalizationTool()
1415: .getPrimaryLocale());
1416: }
1417: }
1418: return issueSearch;
1419: }
1420:
1421: /**
1422: * Get an IssueSearch object based on a query string.
1423: *
1424: * @return a <code>Issue</code> value
1425: */
1426: public IssueSearch getPopulatedSearch(String query)
1427: throws Exception {
1428: IssueSearch search = getNewSearch();
1429: if (null == search)
1430: return null;
1431:
1432: ScarabLocalizationTool l10n = getLocalizationTool();
1433: search.setIssueListAttributeColumns(getRModuleUserAttributes());
1434: search.setLocalizationTool(getLocalizationTool());
1435: search.setQuery(query);
1436:
1437: Intake intake = null;
1438:
1439: if (query == null) {
1440: setInfoMessage(L10NKeySet.EnterQuery);
1441: //IssueSearchFactory.INSTANCE.notifyDone();
1442: //return null;
1443: search.setIsOperable(false);
1444: } else {
1445: intake = parseQuery(query);
1446:
1447: if (!intake.isAllValid()) {
1448: //IssueSearchFactory.INSTANCE.notifyDone();
1449: //return null;
1450: search.setIsOperable(false);
1451: }
1452: }
1453:
1454: // If they have entered users to search on, add them to the search
1455: StringValueParser parser = new StringValueParser();
1456: parser.parse(query, '&', '=', true);
1457: String[] userList = parser.getStrings("user_list");
1458: boolean searchInAllAttributes = parser.getBoolean(
1459: "searchallattributes", false);
1460: if (userList != null && userList.length > 0) {
1461: for (int i = 0; i < userList.length; i++) {
1462: String userId = userList[i];
1463: String[] attrIds = parser.getStrings("user_attr_"
1464: + userId);
1465: if (attrIds != null) {
1466: for (int j = 0; j < attrIds.length; j++) {
1467: search.addUserCriteria(userId, attrIds[j]);
1468: }
1469: }
1470: }
1471: }
1472:
1473: // Set intake properties
1474: int dateFormatErrorCount = 0;
1475: String queryKey = search.getQueryKey();
1476: Group searchGroup = intake.get("SearchIssue", queryKey);
1477:
1478: Field minDate = searchGroup.get("MinDate");
1479: if (minDate != null && minDate.toString().length() > 0) {
1480: dateFormatErrorCount += checkDate(search, minDate);
1481: }
1482:
1483: Field maxDate = searchGroup.get("MaxDate");
1484: if (maxDate != null && maxDate.toString().length() > 0) {
1485: dateFormatErrorCount += checkDate(search, maxDate);
1486: }
1487:
1488: Field stateChangeFromDate = searchGroup
1489: .get("StateChangeFromDate");
1490: if (stateChangeFromDate != null
1491: && stateChangeFromDate.toString().length() > 0) {
1492: dateFormatErrorCount += checkDate(search,
1493: stateChangeFromDate);
1494: }
1495:
1496: Field stateChangeToDate = searchGroup.get("StateChangeToDate");
1497: if (stateChangeToDate != null
1498: && stateChangeToDate.toString().length() > 0) {
1499: dateFormatErrorCount += checkDate(search, stateChangeToDate);
1500: }
1501:
1502: if (dateFormatErrorCount > 0) {
1503: L10NMessage msg = new L10NMessage(
1504: L10NKeySet.DateFormatPrompt,
1505: L10NKeySet.ShortDateDisplay);
1506: setAlertMessage(msg);
1507: //IssueSearchFactory.INSTANCE.notifyDone();
1508: //return null;
1509: search.setIsOperable(false);
1510: }
1511:
1512: if (search.isOperable()) {
1513: try {
1514: searchGroup.setProperties(search);
1515: } catch (Exception e) {
1516: setAlertMessage(l10n.getMessage(e));
1517: //IssueSearchFactory.INSTANCE.notifyDone();
1518: //return null;
1519: search.setIsOperable(false);
1520: }
1521: }
1522:
1523: Integer oldOptionId = search.getStateChangeFromOptionId();
1524: if (oldOptionId != null
1525: && oldOptionId.intValue() != 0
1526: && oldOptionId
1527: .equals(search.getStateChangeToOptionId())) {
1528: setAlertMessage(L10NKeySet.StateChangeOldEqualNew);
1529: //IssueSearchFactory.INSTANCE.notifyDone();
1530: //return null;
1531: search.setIsOperable(false);
1532: }
1533:
1534: // Set attribute values to search on
1535: LinkedMap avMap;
1536: if (searchInAllAttributes) {
1537: avMap = search.getAllAvailableAttributeValuesMap();
1538: } else {
1539: avMap = search.getCommonAttributeValuesMap();
1540: }
1541:
1542: Iterator i = avMap.mapIterator();
1543: while (i.hasNext()) {
1544: Object o = i.next();
1545:
1546: Object av = avMap.get(o);
1547: AttributeValue aval = (AttributeValue) av;
1548:
1549: String qk = aval.getQueryKey();
1550:
1551: Group group = intake.get("AttributeValue", qk);
1552: if (group != null) {
1553: group.setProperties(aval);
1554: }
1555: }
1556:
1557: // If user is sorting on an attribute, set sort criteria
1558: // Do not use intake, since intake parsed from query is not the same
1559: // As intake passed from the form
1560: String sortColumn = data.getParameters()
1561: .getString("sortColumn");
1562: String sortInternal = data.getParameters().getString(
1563: "sortInternal");
1564: if (sortColumn != null && sortColumn.length() > 0
1565: && StringUtils.isNumeric(sortColumn)) {
1566: search.setSortAttributeId(new Integer(sortColumn));
1567: search.setSortInternalAttribute(null);
1568: } else if (sortInternal != null) {
1569: search.setSortInternalAttribute(sortInternal);
1570: search.setSortAttributeId(null);
1571: } else {
1572: // Empty the default sort attribute from the search, so that
1573: // the issue ID will apply.
1574: search.setSortAttributeId(null);
1575: }
1576:
1577: String sortPolarity = data.getParameters().getString(
1578: "sortPolarity");
1579: if (sortPolarity != null && sortPolarity.length() > 0) {
1580: search.setSortPolarity(sortPolarity);
1581: }
1582:
1583: // If an error occured, the search ios returned in an inoperable state.
1584: // The caller must take care of this, since the search itself does not(!)
1585: // obey its own inoperability.
1586:
1587: return search;
1588: }
1589:
1590: /**
1591: * Get an IssueSearch object based on current query string.
1592: *
1593: * @return a <code>Issue</code> value
1594: */
1595: public IssueSearch getPopulatedSearch() throws Exception {
1596: String currentQueryString = ((ScarabUser) data.getUser())
1597: .getMostRecentQuery();
1598: return getPopulatedSearch(currentQueryString);
1599: }
1600:
1601: /**
1602: * Parses query into intake values.
1603: */
1604: public Intake parseQuery(String query) throws Exception {
1605: Intake intake = new Intake();
1606: StringValueParser parser = new StringValueParser();
1607: parser.parse(query, '&', '=', true);
1608:
1609: intake.init(parser);
1610: return intake;
1611: }
1612:
1613: /**
1614: * Performs search on current query (which is stored in user session).
1615: */
1616: public IteratorWithSize getCurrentSearchResults() {
1617: IteratorWithSize matchingIssueIds = null;
1618: try {
1619: matchingIssueIds = getUnprotectedCurrentSearchResults();
1620: } catch (MaxConcurrentSearchException e) {
1621: setAlertMessage(L10NKeySet.ResourceLimitationsPreventedSearch);
1622: } catch (ComplexQueryException e) {
1623: matchingIssueIds = IteratorWithSize.EMPTY;
1624: setAlertMessage(new SimpleSkipFiltering(
1625: getLocalizationTool().format(
1626: "SearchAbortedDueToComplexity",
1627: new SnippetRenderer(data,
1628: "ComplexQueryHelpLink.vm"))));
1629: } catch (Exception e) {
1630: matchingIssueIds = IteratorWithSize.EMPTY;
1631: L10NMessage l10nMessage = new L10NMessage(
1632: L10NKeySet.ErrorProcessingQuery, e);
1633: setAlertMessage(l10nMessage);
1634: Log.get().info("Error processing a query", e);
1635: }
1636:
1637: return matchingIssueIds;
1638: }
1639:
1640: /**
1641: * Caches the result of getUncachedCurrentSearchResults for the remainder
1642: * of the request.
1643: */
1644: private IteratorWithSize getUnprotectedCurrentSearchResults()
1645: throws Exception {
1646: // normally we would use "this" as the first arg to ScarabCache.get,
1647: // but SRT is not serializable. The result is a mix of a query string
1648: // and an MITList and the two should not vary over the course of one
1649: // request so use the query string as the key. We were using the
1650: // IssueSearch returned by getNewSearch as the key, but we have to
1651: // call user.getMostRecentQuery prior to getNewSearch, so using
1652: // that instead.
1653: String queryString = ((ScarabUser) data.getUser())
1654: .getMostRecentQuery();
1655: IteratorWithSize results = null;
1656: Object obj = ScarabCache.get(queryString,
1657: "getUnprotectedCurrentSearchResults");
1658: if (obj == null) {
1659: results = getUncachedCurrentSearchResults();
1660: ScarabCache.put(results, queryString,
1661: "getUnprotectedCurrentSearchResults");
1662: } else {
1663: results = (IteratorWithSize) obj;
1664: }
1665: return results;
1666: }
1667:
1668: /**
1669: * Performs search on current query (which is stored in user session).
1670: */
1671: private IteratorWithSize getUncachedCurrentSearchResults()
1672: throws Exception {
1673: ScarabLocalizationTool l10n = getLocalizationTool();
1674: ScarabUser user = (ScarabUser) data.getUser();
1675: String currentQueryString = user.getMostRecentQuery();
1676: IssueSearch search = getPopulatedSearch(currentQueryString);
1677: IteratorWithSize queryResults = null;
1678:
1679: // Do search
1680: try {
1681: if (search == null) {
1682: // an alert message should have been set while attempting
1683: // to populate the search.
1684: queryResults = IteratorWithSize.EMPTY;
1685: } else {
1686: queryResults = search.getQueryResults(true);
1687: if (!queryResults.hasNext()) {
1688: setInfoMessage(L10NKeySet.NoMatchingIssues);
1689: }
1690: }
1691: } catch (ScarabException e) {
1692: String queryError = e.getMessage();
1693: if (queryError.startsWith(SearchIndex.PARSE_ERROR)) {
1694: Log.get().info(queryError);
1695: setAlertMessage(new SimpleSkipFiltering(l10n.format(
1696: "QueryParserError", new SnippetRenderer(data,
1697: "TextQueryHelp.vm"))));
1698: } else {
1699: throw e; //EXCEPTION
1700: }
1701: } finally {
1702: if (search != null) {
1703: IssueSearchFactory.INSTANCE.notifyDone();
1704: }
1705: }
1706: return queryResults;
1707: }
1708:
1709: /**
1710: * Gets the number of results for the current query. Looks first
1711: * at the URL, then re-queries if size information is missing.
1712: */
1713: public int getCurrentSearchResultsSize() {
1714: String[] prevNextList = data.getParameters().getStrings(
1715: "issueList");
1716: int result = 0;
1717: if (prevNextList == null) {
1718: result = getCurrentSearchResults().size();
1719: } else {
1720: result = Integer.parseInt(prevNextList[1]);
1721: }
1722: return result;
1723: }
1724:
1725: /**
1726: * Returns the issue's position (1-based) in current issue list.
1727: */
1728: public int getIssuePosInList() throws Exception, ScarabException {
1729: int issuePos = -1;
1730: String id = getIssue().getUniqueId();
1731: String[] prevNextList = data.getParameters().getStrings(
1732: "issueList");
1733: if (prevNextList != null) {
1734: int listOffset = Math.max(0, Integer
1735: .parseInt(prevNextList[0]));
1736: for (int i = 2; i < prevNextList.length; i++) {
1737: if (prevNextList[i].equals(id)) {
1738: issuePos = listOffset + i - 1;
1739: break;
1740: }
1741: }
1742: }
1743:
1744: return (issuePos <= 0) ? 1 : issuePos;
1745: }
1746:
1747: /**
1748: * Returns next issue id in list.
1749: */
1750: public String getNextIssue() throws Exception, ScarabException {
1751: String nextIssueId = null;
1752: String[] prevNextList = data.getParameters().getStrings(
1753: "issueList");
1754: if (prevNextList != null) {
1755: String id = getIssue().getUniqueId();
1756: for (int i = 2; i < prevNextList.length - 1; i++) {
1757: if (prevNextList[i].equals(id)) {
1758: nextIssueId = prevNextList[i + 1];
1759: break;
1760: }
1761: }
1762: }
1763:
1764: if (nextIssueId == null) {
1765: if (cachedNextIssueId == null) {
1766: int issuePos = getIssuePosInList();
1767: if (issuePos <= getCurrentSearchResultsSize()) {
1768: resetIssueIdList(issuePos);
1769: nextIssueId = cachedNextIssueId;
1770: }
1771: } else {
1772: nextIssueId = cachedNextIssueId;
1773: }
1774: }
1775: return nextIssueId;
1776: }
1777:
1778: /**
1779: * Returns previous issue id in list.
1780: */
1781: public String getPrevIssue() throws Exception, ScarabException {
1782: String prevIssueId = null;
1783: String[] prevNextList = data.getParameters().getStrings(
1784: "issueList");
1785: if (prevNextList != null) {
1786: String id = getIssue().getUniqueId();
1787: for (int i = 3; i < prevNextList.length; i++) {
1788: if (prevNextList[i].equals(id)) {
1789: prevIssueId = prevNextList[i - 1];
1790: break;
1791: }
1792: }
1793: }
1794:
1795: if (prevIssueId == null) {
1796: if (cachedPrevIssueId == null) {
1797: int issuePos = getIssuePosInList();
1798: if (issuePos > 1) {
1799: resetIssueIdList(issuePos);
1800: prevIssueId = cachedPrevIssueId;
1801: }
1802: } else {
1803: prevIssueId = cachedPrevIssueId;
1804: }
1805: }
1806: return prevIssueId;
1807: }
1808:
1809: private void resetIssueIdList(int issuePos) {
1810: IteratorWithSize idList = getCurrentSearchResults();
1811: ParameterParser pp = data.getParameters();
1812: pp.remove("issueList");
1813: int min = issuePos - 5;
1814: int max = issuePos + 10;
1815: pp.add("issueList", min);
1816: pp.add("issueList", idList.size());
1817:
1818: int count;
1819: for (count = 0; idList.hasNext() && count < min; count++) {
1820: idList.next();
1821: }
1822: for (; idList.hasNext() && count < issuePos - 2; count++) {
1823: pp.add("issueList", ((QueryResult) idList.next())
1824: .getUniqueId());
1825: }
1826: if (idList.hasNext()) {
1827: cachedPrevIssueId = ((QueryResult) idList.next())
1828: .getUniqueId();
1829: pp.add("issueList", cachedPrevIssueId);
1830: }
1831: if (idList.hasNext()) {
1832: pp.add("issueList", ((QueryResult) idList.next())
1833: .getUniqueId());
1834: }
1835: if (idList.hasNext()) {
1836: cachedNextIssueId = ((QueryResult) idList.next())
1837: .getUniqueId();
1838: pp.add("issueList", cachedNextIssueId);
1839: }
1840: for (count += 3; idList.hasNext() && count < max; count++) {
1841: pp.add("issueList", ((QueryResult) idList.next())
1842: .getUniqueId());
1843: }
1844: }
1845:
1846: /**
1847: * Attempts to parse a date passed in the query page.
1848: */
1849: private int checkDate(IssueSearch search, Field dateField)
1850: throws Exception {
1851: int errorCount = 0;
1852: try {
1853: String date = dateField.toString();
1854: search.parseDate(date, false);
1855: } catch (Exception e) {
1856: errorCount = 1;
1857: dateField.setMessage("format error [" + e.getMessage()
1858: + "]");
1859: }
1860: return errorCount;
1861: }
1862:
1863: /**
1864: * Convert paths with slashes to commas.
1865: */
1866: public String convertPath(String path) throws Exception {
1867: return path.replace('/', ',');
1868: }
1869:
1870: /**
1871: * Returns all issue templates that are global,
1872: * Plus those that are personal and created by logged-in user.
1873: */
1874: public List getAllIssueTemplates(IssueType issueType)
1875: throws Exception {
1876: ParameterParser params = data.getParameters();
1877: String sortColumn = params.getString("sortColumn", "name");
1878: String sortPolarity = params.getString("sortPolarity", "asc");
1879: return IssueTemplateInfoPeer.getTemplates(getCurrentModule(),
1880: issueType, (ScarabUser) data.getUser(), sortColumn,
1881: sortPolarity, IssueTemplateInfoPeer.TYPE_ALL);
1882: }
1883:
1884: /**
1885: * Returns templates that are personal and created by logged-in user.
1886: */
1887: public List getPrivateTemplates(IssueType issueType)
1888: throws Exception {
1889: return IssueTemplateInfoPeer.getTemplates(getCurrentModule(),
1890: issueType, (ScarabUser) data.getUser(), "name", "asc",
1891: IssueTemplateInfoPeer.TYPE_PRIVATE);
1892: }
1893:
1894: /**
1895: * Returns templates that are personal and created by logged-in user.
1896: */
1897: public List getGlobalTemplates(IssueType issueType)
1898: throws Exception {
1899: return IssueTemplateInfoPeer.getTemplates(getCurrentModule(),
1900: issueType, (ScarabUser) data.getUser(), "name", "asc",
1901: IssueTemplateInfoPeer.TYPE_GLOBAL);
1902: }
1903:
1904: /**
1905: * Returns all queries that are global,
1906: * Plus those that are personal and created by logged-in user.
1907: */
1908: public List getAllQueries() throws Exception {
1909: String sortColumn = data.getParameters()
1910: .getString("sortColumn");
1911: String sortPolarity = data.getParameters().getString(
1912: "sortPolarity");
1913: if (sortColumn == null) {
1914: sortColumn = "avail";
1915: }
1916: if (sortPolarity == null) {
1917: sortPolarity = "desc";
1918: }
1919: return QueryPeer.getQueries(getCurrentModule(), null,
1920: (ScarabUser) data.getUser(), sortColumn, sortPolarity,
1921: IssueTemplateInfoPeer.TYPE_ALL);
1922: }
1923:
1924: /**
1925: * Returns queries that are personal and created by logged-in user.
1926: */
1927: public List getPrivateQueries() throws Exception {
1928: return QueryPeer.getQueries(getCurrentModule(), null,
1929: (ScarabUser) data.getUser(), "name", "asc",
1930: QueryPeer.TYPE_PRIVATE);
1931: }
1932:
1933: /**
1934: * Returns queries that are personal and created by logged-in user.
1935: */
1936: public List getUserQueries() throws Exception {
1937: return QueryPeer.getQueries(getCurrentModule(), null,
1938: (ScarabUser) data.getUser(), "name", "asc",
1939: QueryPeer.TYPE_ALL_USER);
1940: }
1941:
1942: /**
1943: * Returns all queries that are global.
1944: */
1945: public List getGlobalQueries() throws Exception {
1946: return QueryPeer.getQueries(getCurrentModule(), null,
1947: (ScarabUser) data.getUser(), "name", "asc",
1948: QueryPeer.TYPE_GLOBAL);
1949: }
1950:
1951: /**
1952: * Returns all queries global for the module
1953: */
1954: public List getGlobalQueries(Module module) throws Exception {
1955: return QueryPeer.getQueries(module, null, (ScarabUser) data
1956: .getUser(), "name", "asc", QueryPeer.TYPE_GLOBAL);
1957: }
1958:
1959: /**
1960: * Returns all queries that are global.
1961: */
1962: public List getUserAllQueries() throws Exception {
1963: return QueryPeer.getQueries(getCurrentModule(), null,
1964: (ScarabUser) data.getUser(), "name", "asc",
1965: QueryPeer.TYPE_ALL_USER);
1966: }
1967:
1968: /**
1969: * a report helper class
1970: */
1971: public ReportBridge getReport() throws Exception {
1972: if (reportGenerator == null) {
1973: String key = data.getParameters().getString(
1974: ScarabConstants.CURRENT_REPORT);
1975: ParameterParser parameters = data.getParameters();
1976: String id = parameters.getString("report_id");
1977: if (id == null || id.length() == 0) {
1978: ScarabUser user = (ScarabUser) data.getUser();
1979: MITList mitlist = user.getCurrentMITList();
1980: if (key == null) {
1981: reportGenerator = getNewReport(mitlist);
1982: } else {
1983: reportGenerator = user.getCurrentReport(key);
1984:
1985: // if reportingIssue is still null, the parameter must have
1986: // been stale, just get a new report
1987: if (reportGenerator == null && mitlist != null
1988: && !mitlist.isEmpty()) {
1989: reportGenerator = getNewReport(mitlist);
1990: }
1991: }
1992: } else {
1993: reportGenerator = new ReportBridge(ReportManager
1994: .getInstance(new NumberKey(id), false));
1995: key = ((ScarabUser) data.getUser())
1996: .setCurrentReport(reportGenerator);
1997: data.getParameters().remove(
1998: ScarabConstants.CURRENT_REPORT);
1999: data.getParameters().add(
2000: ScarabConstants.CURRENT_REPORT, key);
2001: }
2002: }
2003:
2004: return reportGenerator;
2005: }
2006:
2007: private ReportBridge getNewReport(MITList mitList) throws Exception {
2008: if (mitList == null) {
2009: throw new IllegalArgumentException(
2010: "Cannot create a new report without any issue types."); //EXCEPTION
2011: }
2012:
2013: ScarabUser user = (ScarabUser) data.getUser();
2014: org.tigris.scarab.om.Report om = new org.tigris.scarab.om.Report();
2015: ReportBridge report = new ReportBridge(om);
2016: report.setGeneratedBy(user);
2017: report.setMITList(mitList);
2018:
2019: String key = ((ScarabUser) data.getUser())
2020: .setCurrentReport(report);
2021: data.getParameters().add(ScarabConstants.CURRENT_REPORT, key);
2022:
2023: return report;
2024: }
2025:
2026: public void setReport(ReportBridge report) {
2027: this .reportGenerator = report;
2028: }
2029:
2030: /**
2031: * Full featured, paginated, sorted method for returning the results
2032: * of user search. Returns all users (no search criteria).
2033: */
2034: public ScarabPaginatedList getUserSearchResults(MITList mitList,
2035: int pageNum, int resultsPerPage, String sortColumn,
2036: String sortPolarity, boolean includeCommitters)
2037: throws Exception {
2038: return userFilteredSearchResults(mitList, pageNum,
2039: resultsPerPage, sortColumn, sortPolarity, "", "",
2040: includeCommitters);
2041: }
2042:
2043: /**
2044: * Full featured, paginated, sorted version for returning results
2045: * of a user search.
2046: */
2047: public ScarabPaginatedList getUserFilteredSearchResults(
2048: MITList mitList, int pageNum, int resultsPerPage,
2049: String sortColumn, String sortPolarity,
2050: boolean includeCommitters) throws Exception {
2051: String searchString = data.getParameters().getString(
2052: "searchString");
2053: String searchField = data.getParameters().getString(
2054: "searchField");
2055:
2056: if (searchField == null) {
2057: setInfoMessage(L10NKeySet.SearchFieldPrompt);
2058: return null;
2059: }
2060:
2061: return userFilteredSearchResults(mitList, pageNum,
2062: resultsPerPage, sortColumn, sortPolarity, searchString,
2063: searchField, includeCommitters);
2064:
2065: }
2066:
2067: private ScarabPaginatedList userFilteredSearchResults(
2068: MITList mitList, int pageNum, int resultsPerPage,
2069: String sortColumn, String sortPolarity,
2070: String searchString, String searchField,
2071: boolean includeCommitters) throws Exception {
2072: ScarabPaginatedList list = null;
2073: String name = null;
2074: String userName = null;
2075:
2076: if ("FullName".equalsIgnoreCase(searchField)) {
2077: name = searchString;
2078: } else if ("UserName".equalsIgnoreCase(searchField)) {
2079: userName = searchString;
2080: }
2081:
2082: try {
2083: list = getCurrentModule().getUsers(name, userName, mitList,
2084: pageNum, resultsPerPage, sortColumn, sortPolarity,
2085: includeCommitters);
2086: } catch (Exception e) {
2087: Log.get().error("Problem getting user list", e);
2088: list = new ScarabPaginatedList();
2089: }
2090:
2091: // These are object members are used by GlobalMacros.vm via
2092: // the bean interface. Leave them here until all users of the
2093: // paginate macro can be updated.
2094: this .nbrPages = list.getNumberOfPages();
2095: this .nextPage = list.getNextPageNumber();
2096: this .prevPage = list.getPrevPageNumber();
2097:
2098: return list;
2099: }
2100:
2101: /**
2102: * Return results of attribute search.
2103: */
2104: public List getAttributeSearchResults() throws Exception {
2105: String searchString = data.getParameters().getString(
2106: "searchString");
2107: String searchField = data.getParameters().getString(
2108: "searchField");
2109: if (searchField == null) {
2110: setInfoMessage(L10NKeySet.SearchFieldPrompt);
2111: return null;
2112: }
2113:
2114: String name = null;
2115: String description = null;
2116: if (searchField.equals("Name") || searchField.equals("Any")) {
2117: name = searchString;
2118: }
2119: if (searchField.equals("Description")
2120: || searchField.equals("Any")) {
2121: description = searchString;
2122: }
2123:
2124: return sortAttributes(AttributePeer.getFilteredAttributes(name,
2125: description, searchField));
2126: }
2127:
2128: /**
2129: * Sort users on name or email.
2130: */
2131: public List sortUsers(List userList) throws Exception {
2132: final String sortColumn = data.getParameters().getString(
2133: "sortColumn");
2134: final String sortPolarity = data.getParameters().getString(
2135: "sortPolarity");
2136: final int polarity = ("desc".equals(sortPolarity)) ? -1 : 1;
2137: Comparator c = new Comparator() {
2138: public int compare(Object o1, Object o2) {
2139: int i = 0;
2140: if ("username".equals(sortColumn)) {
2141: i = polarity
2142: * ((ScarabUser) o1).getUserName()
2143: .compareTo(
2144: ((ScarabUser) o2)
2145: .getUserName());
2146: } else {
2147: i = polarity
2148: * ((ScarabUser) o1).getName().compareTo(
2149: ((ScarabUser) o2).getName());
2150: }
2151: return i;
2152: }
2153: };
2154: Collections.sort(userList, c);
2155: return userList;
2156: }
2157:
2158: /**
2159: * Sort attributes on name or description.
2160: */
2161: public List sortAttributes(List attList) throws Exception {
2162: final String sortColumn = data.getParameters().getString(
2163: "sortColumn");
2164: final String sortPolarity = data.getParameters().getString(
2165: "sortPolarity");
2166: final int polarity = ("desc".equals(sortPolarity)) ? -1 : 1;
2167: Comparator c = new Comparator() {
2168: public int compare(Object o1, Object o2) {
2169: int i = 0;
2170: if (sortColumn != null && sortColumn.equals("name")) {
2171: i = polarity
2172: * ((Attribute) o1).getName().compareTo(
2173: ((Attribute) o2).getName());
2174: } else {
2175: i = polarity
2176: * ((Attribute) o1).getDescription()
2177: .compareTo(
2178: ((Attribute) o2)
2179: .getDescription());
2180: }
2181: return i;
2182: }
2183: };
2184: Collections.sort(attList, c);
2185: return attList;
2186: }
2187:
2188: /**
2189: * Return a subset of the passed-in list.
2190: *
2191: * @param nbrItmsPerPage negative value returns full list
2192: */
2193: public List getPaginatedList(List fullList, int pgNbr,
2194: int nbrItmsPerPage) {
2195: List pageResults = null;
2196: try {
2197: if (nbrItmsPerPage < 0) {
2198: pageResults = fullList;
2199: } else {
2200: this .nbrPages = (int) Math.ceil((float) fullList.size()
2201: / nbrItmsPerPage);
2202: this .nextPage = pgNbr + 1;
2203: this .prevPage = pgNbr - 1;
2204: pageResults = fullList.subList((pgNbr - 1)
2205: * nbrItmsPerPage, Math.min(pgNbr
2206: * nbrItmsPerPage, fullList.size()));
2207: }
2208: } catch (Exception e) {
2209: Log.get().error("", e);
2210: }
2211: return pageResults;
2212: }
2213:
2214: /**
2215: * Return a subset of the passed-in list.
2216: *
2217: * @param nbrItmsPerPage negative value returns full list
2218: */
2219: public IteratorWithSize getPaginatedIterator(
2220: IteratorWithSize fullList, int pgNbr, int nbrItmsPerPage) {
2221: IteratorWithSize pageResults;
2222: try {
2223: if (nbrItmsPerPage < 0) {
2224: pageResults = fullList;
2225: } else {
2226: this .nbrPages = (int) Math.ceil((float) fullList.size()
2227: / nbrItmsPerPage);
2228: this .nextPage = pgNbr + 1;
2229: this .prevPage = pgNbr - 1;
2230: pageResults = new SubsetIteratorWithSize(fullList,
2231: (pgNbr - 1) * nbrItmsPerPage, nbrItmsPerPage);
2232: }
2233: } catch (Exception e) {
2234: Log.get().error("", e);
2235: pageResults = IteratorWithSize.EMPTY;
2236: }
2237: return pageResults;
2238: }
2239:
2240: /**
2241: * Checks for a query parameter "oldResultsPerPage" and compares it
2242: * to the current "resultsPerPage" parameter. If they are different,
2243: * it returns 1 to avoid returning a value larger than the maximum
2244: * number of pages; otherwise it returns the value of the query parameter
2245: * "pageNum".
2246: * Preferable optimization would be to adjust the page number to
2247: * keep a set of the old displayed items on the new page.
2248: */
2249: public int getAdjustedPageNum() {
2250: ParameterParser parameters = data.getParameters();
2251: int resultsPerPage = parameters.getInt("resultsPerPage", 0);
2252: int oldResultsPerPage = parameters.getInt("oldResultsPerPage",
2253: 0);
2254: int pageNum = parameters.getInt("pageNum", 1);
2255: // I seem to be too brain dead to come up with a formula to return the
2256: // new page that will contain the first item on the last page we
2257: // viewed.
2258: // forget it and start over
2259:
2260: // Note that -1 -> All results
2261: if (oldResultsPerPage != 0
2262: && oldResultsPerPage != resultsPerPage) {
2263: pageNum = 1;
2264: }
2265: return pageNum;
2266: }
2267:
2268: /**
2269: * Return the number of paginated pages.
2270: *
2271: */
2272: public int getNbrPages() {
2273: return nbrPages;
2274: }
2275:
2276: /**
2277: * Return the next page in the paginated list.
2278: *
2279: */
2280: public int getNextPage() {
2281: if (nextPage <= nbrPages) {
2282: return nextPage;
2283: } else {
2284: return 0;
2285: }
2286: }
2287:
2288: /**
2289: * Return the previous page in the paginated list.
2290: *
2291: */
2292: public int getPrevPage() {
2293: return prevPage;
2294: }
2295:
2296: /**
2297: * This is used to get the format for a date in the
2298: * Locale sent by the browser.
2299: */
2300: public DateFormat getDateFormat() {
2301: Locale locale = Localization.getLocale(data.getRequest());
2302: DateFormat df = DateFormat.getDateTimeInstance(
2303: DateFormat.MEDIUM, DateFormat.LONG, locale);
2304: if (timezone != null) {
2305: df.setTimeZone(timezone);
2306: }
2307: return df;
2308:
2309: // We may want to eventually format the date other than default,
2310: // this is how you would do it.
2311: //SimpleDateFormat sdf = new SimpleDateFormat(
2312: // "yyyy/MM/dd hh:mm:ss a z", locale);
2313: //return (DateFormat) sdf;
2314: }
2315:
2316: /**
2317: * This is used to get the format for a date in the
2318: * Locale sent by the browser.
2319: */
2320: public Calendar getCalendar() {
2321: Locale locale = Localization.getLocale(data.getRequest());
2322: Calendar cal = Calendar.getInstance(locale);
2323: if (timezone != null) {
2324: cal.setTimeZone(timezone);
2325: }
2326: return cal;
2327: }
2328:
2329: /**
2330: * Determine if the user currently interacting with the scarab
2331: * application has a permission within the user's currently
2332: * selected module.
2333: *
2334: * @param permission a <code>String</code> permission value, which should
2335: * be a constant in this interface.
2336: * @return true if the permission exists for the user within the
2337: * current module, false otherwise
2338: */
2339: public boolean hasPermission(String permission) {
2340: boolean hasPermission = false;
2341: try {
2342: Module module = getCurrentModule();
2343: hasPermission = hasPermission(permission, module);
2344: } catch (Exception e) {
2345: hasPermission = false;
2346: Log.get().error("Permission check failed on:" + permission,
2347: e);
2348: }
2349: return hasPermission;
2350: }
2351:
2352: /**
2353: * Determine if the user currently interacting with the scarab
2354: * application has a permission within a module.
2355: *
2356: * @param permission a <code>String</code> permission value, which should
2357: * be a constant in this interface.
2358: * @param module a <code>Module</code> value
2359: * @return true if the permission exists for the user within the
2360: * given module, false otherwise
2361: */
2362: public boolean hasPermission(String permission, Module module) {
2363: boolean hasPermission = false;
2364: try {
2365: hasPermission = ((ScarabUser) data.getUser())
2366: .hasPermission(permission, module);
2367: } catch (Exception e) {
2368: hasPermission = false;
2369: Log.get().error("Permission check failed on:" + permission,
2370: e);
2371: }
2372: return hasPermission;
2373: }
2374:
2375: /* The map of associated users used on AssignIssue
2376: * When we first go to the screen, reset the map
2377: * To the currently assigned users for each issue
2378: */
2379: public void resetAssociatedUsers() throws Exception {
2380: HashMap assoUsers = new HashMap();
2381: List issueList = getIssues();
2382: if (issueList != null) {
2383: for (int i = 0; i < issueList.size(); i++) {
2384: Issue issue = (Issue) issueList.get(i);
2385: assoUsers.put(issue.getIssueId(), issue
2386: .getAssociatedUsers());
2387: }
2388: ((ScarabUser) data.getUser())
2389: .setAssociatedUsersMap(assoUsers);
2390: }
2391: }
2392:
2393: public void resetSelectedUsers() throws Exception {
2394: ScarabUser user = (ScarabUser) data.getUser();
2395: user.setSelectedUsersMap(null);
2396: }
2397:
2398: /**
2399: * When a user searches for other users (in the ManageUserSearch.vm
2400: * template for example), the result of this search is stored into
2401: * the temporary data for that user. This previous result can be
2402: * retrieved by this method.
2403: *
2404: * FIXME: shouldn't this be stored into the cache instead of the
2405: * temporary data of the user?
2406: *
2407: * @return The list of users of the last user-search.
2408: */
2409: public List getGlobalUserSearch() {
2410: List users = (List) data.getUser().getTemp("userList");
2411: if (users == null) {
2412: users = new ArrayList();
2413: }
2414: return users;
2415: }
2416:
2417: public ScarabPaginatedList getPaginatedGlobalUsersList(int pageNum,
2418: int resultsPerPage, String searchField,
2419: String searchCriteria, String sortColumn,
2420: String sortPolarity) throws Exception {
2421: ScarabPaginatedList paginated;
2422: Criteria crit = new Criteria();
2423: Criteria critCount = new Criteria();
2424: crit.setOffset((pageNum - 1) * resultsPerPage);
2425: crit.setLimit(resultsPerPage);
2426: crit.add(ScarabUserImplPeer.USER_ID,
2427: (Object) (ScarabUserImplPeer.USER_ID + " IS NOT NULL"),
2428: Criteria.CUSTOM);
2429: crit.addNotIn(ScarabUserImplPeer.CONFIRM_VALUE,
2430: new Object[] { "DELETED" });
2431: critCount.addNotIn(ScarabUserImplPeer.CONFIRM_VALUE,
2432: new Object[] { "DELETED" });
2433:
2434: if (searchField != null) {
2435: if (searchField.equals("LOGIN_NAME"))
2436: searchField = ScarabUserImplPeer.LOGIN_NAME;
2437: else if (searchField.equals("LAST_NAME"))
2438: searchField = ScarabUserImplPeer.LAST_NAME;
2439: else if (searchField.equals("FIRST_NAME"))
2440: searchField = ScarabUserImplPeer.FIRST_NAME;
2441: else if (searchField.equals("EMAIL"))
2442: searchField = ScarabUserImplPeer.EMAIL;
2443: crit.add(searchField,
2444: (Object) ("%" + searchCriteria + "%"),
2445: Criteria.LIKE);
2446: critCount.add(searchField,
2447: (Object) ("%" + searchCriteria + "%"),
2448: Criteria.LIKE);
2449:
2450: String col = ScarabUserImplPeer.FIRST_NAME;
2451: if (sortColumn.equals("LOGIN_NAME"))
2452: col = ScarabUserImplPeer.LOGIN_NAME;
2453: else if (sortColumn.equals("LAST_NAME"))
2454: col = ScarabUserImplPeer.LAST_NAME;
2455: else if (sortColumn.equals("FIRST_NAME"))
2456: col = ScarabUserImplPeer.FIRST_NAME;
2457: else if (sortColumn.equals("EMAIL"))
2458: col = ScarabUserImplPeer.EMAIL;
2459: if (sortPolarity.equalsIgnoreCase("asc")) {
2460: crit.addAscendingOrderByColumn(col);
2461: } else {
2462: crit.addDescendingOrderByColumn(col);
2463: }
2464: }
2465:
2466: critCount.add(ScarabUserImplPeer.USER_ID,
2467: (Object) (ScarabUserImplPeer.USER_ID + " IS NOT NULL"),
2468: Criteria.CUSTOM);
2469: List result = ScarabUserImplPeer.doSelect(crit);
2470: critCount.addSelectColumn("COUNT(*)");
2471: int totalResultSize = ScarabUserImplPeer
2472: .getUsersCount(critCount);
2473: if (totalResultSize > 0 && resultsPerPage > 0) {
2474:
2475: paginated = new ScarabPaginatedList(result,
2476: totalResultSize, pageNum, resultsPerPage);
2477: } else {
2478: paginated = new ScarabPaginatedList();
2479: }
2480:
2481: return paginated;
2482: }
2483:
2484: /**
2485: * Store the search result of other users for later use. The
2486: * result is stored into the temporary data of the current user.
2487: *
2488: * FIXME: use the cache instead?
2489: *
2490: * @param users The list of users that is a result of a query.
2491: */
2492: public void setGlobalUserSearch(List users) {
2493: data.getUser().setTemp("userList", users);
2494: }
2495:
2496: /**
2497: * Return the parameter used for the user-search (like in the
2498: * ManageUserSearch.vm template for example) returned by the
2499: * getGlobalUserSearch() method. These parameters are stored
2500: * into the temporary data of the current user.
2501: *
2502: * FIXME: use the cache instead?
2503: *
2504: * @param name The name of the parameter
2505: * @return The value of the parameter used in the search for users.
2506: */
2507: public String getGlobalUserSearchParam(String name) {
2508: Hashtable params = (Hashtable) data.getUser().getTemp(
2509: "userListParams");
2510:
2511: if (params == null) {
2512: return "";
2513: }
2514:
2515: return (String) params.get(name);
2516: }
2517:
2518: /**
2519: * Set the parameters used to retrieved the users in the List given
2520: * to the setGlobalUserSearch(List) method. These parameters can be
2521: * retrieved by the getGlobalUserSearchParam(String) for later use.
2522: *
2523: * FIXME: use the cache instead?
2524: *
2525: * @param name The name of the parameter
2526: * @param value The value of the parameter
2527: */
2528: public void setGlobalUserSearchParam(String name, String value) {
2529: Hashtable params = (Hashtable) data.getUser().getTemp(
2530: "userListParams");
2531: if (params == null) {
2532: params = new Hashtable();
2533: }
2534:
2535: if ((name != null) && (value != null)) {
2536: params.put(name, value);
2537: }
2538: data.getUser().setTemp("userListParams", params);
2539: }
2540:
2541: public boolean hasItemsToApprove() {
2542: try {
2543: SecurityAdminTool sat = (SecurityAdminTool) org.apache.turbine.modules.Module
2544: .getTemplateContext(data).get(
2545: ScarabConstants.SECURITY_ADMIN_TOOL);
2546: if (getCurrentModule().getUnapprovedQueries().isEmpty()
2547: && getCurrentModule().getUnapprovedTemplates()
2548: .isEmpty()
2549: && sat.getPendingGroupUserRoles(getCurrentModule())
2550: .isEmpty()) {
2551: return false;
2552: }
2553: } catch (Exception e) {
2554: Log.get().debug("Error: ", e);
2555: }
2556: return true;
2557: }
2558:
2559: public MITList getMITList(List issues) throws Exception {
2560: return MITListManager.getInstanceFromIssueList(issues,
2561: (ScarabUser) data.getUser());
2562: }
2563:
2564: /**
2565: * Create a MITListItem from an RModuleIssueType instance.
2566: * @param rmits
2567: * @return
2568: * @throws TorqueException
2569: */
2570: public static MITListItem convertToMITListItem(RModuleIssueType rmit)
2571: throws TorqueException {
2572: MITListItem item = MITListItemManager.getInstance();
2573: item.setModuleId(rmit.getModuleId());
2574: item.setIssueTypeId(rmit.getIssueTypeId());
2575: return item;
2576: }
2577:
2578: /**
2579: * Gets a list of Attributes or the user type that are in common
2580: * between the issues in the given list.
2581: *
2582: * @param issues a <code>List</code> value
2583: * @return a <code>List</code> value
2584: * @exception Exception if an error occurs
2585: */
2586: public List getUserAttributes(List issues, boolean activeOnly)
2587: throws Exception {
2588: List attributes = null;
2589: if (issues == null || issues.isEmpty()) {
2590: attributes = Collections.EMPTY_LIST;
2591: Log.get().warn(
2592: "ScarabRequestTool.getUserAttributes issue list was"
2593: + (issues == null ? " null" : " empty"));
2594: } else {
2595: attributes = getMITList(issues).getCommonUserAttributes(
2596: activeOnly);
2597: }
2598:
2599: return attributes;
2600: }
2601:
2602: // --------------------
2603: // template timing methods
2604: private long startTime;
2605: private long lapTime;
2606:
2607: /**
2608: * Should be called near the beginning of a template or wherever timing
2609: * should start.
2610: */
2611: public void startTimer() {
2612: startTime = System.currentTimeMillis();
2613: lapTime = startTime;
2614: }
2615:
2616: /**
2617: * Useful when performance tuning. Usage is to call
2618: * <pre><code>
2619: * $scarabR.startTimer()
2620: * ...
2621: * $scarabR.reportTimer("foo")
2622: * ...
2623: * $scarabR.reportTimer("bar")
2624: *
2625: * or
2626: *
2627: * $scarabG.log($scarabR.reportTimer("bar"))
2628: * </code></pre>
2629: *
2630: * The labels are useful when output is directed to a log file, it can
2631: * be "", if the output is written as part of the response.
2632: */
2633: public String reportTimer(String mesg) {
2634: long endTime = System.currentTimeMillis();
2635: String s = mesg + ". Time for " + data.getTarget()
2636: + ": Lap/Split= " + (endTime - lapTime)
2637: + "ms; Cumulative= " + (endTime - startTime) + "ms";
2638: lapTime = endTime;
2639: return s;
2640: }
2641:
2642: /**
2643: * Helper method to retrieve the ScarabLocalizationTool from the Context
2644: */
2645: private ScarabLocalizationTool getLocalizationTool() {
2646: return (ScarabLocalizationTool) org.apache.turbine.modules.Module
2647: .getTemplateContext(data).get(
2648: ScarabConstants.LOCALIZATION_TOOL);
2649: }
2650:
2651: /**
2652: * Get any confirmation message usually set in the action.
2653: * @return value of confirmMessage.
2654: */
2655: public Object getConfirmMessage() {
2656: return confirmMessage;
2657: }
2658:
2659: /**
2660: * Set confirmation message.
2661: * @deprecated
2662: * @param v Value to assign to confirmMessage.
2663: */
2664: public void setConfirmMessage(Object v) {
2665: this .confirmMessage = v;
2666: }
2667:
2668: /**
2669: * Set confirm message using Localizable localizable.
2670: * @param v Value to assign to alertMessage.
2671: */
2672: public void setConfirmMessage(Localizable localizable) {
2673: ScarabLocalizationTool l10n = getLocalizationTool();
2674: this .confirmMessage = new SimpleSkipFiltering(localizable
2675: .getMessage(l10n));
2676: }
2677:
2678: /**
2679: * Get any informational message usually set in the action.
2680: * @return value of infoMessage.
2681: */
2682: public Object getInfoMessage() {
2683: return infoMessage;
2684: }
2685:
2686: /**
2687: * Set informational message.
2688: * @deprecated
2689: * @param v Value to assign to infoMessage.
2690: */
2691: public void setInfoMessage(Object v) {
2692: this .infoMessage = v;
2693: }
2694:
2695: /**
2696: * Set alert message using Localizable localizable.
2697: * @param v Value to assign to alertMessage.
2698: */
2699: public void setInfoMessage(Localizable localizable) {
2700: ScarabLocalizationTool l10n = getLocalizationTool();
2701: this .infoMessage = new SimpleSkipFiltering(localizable
2702: .getMessage(l10n));
2703: }
2704:
2705: /**
2706: * Get any alert message usually set in the action.
2707: * @return value of alertMessage.
2708: */
2709: public Object getAlertMessage() {
2710: return alertMessage;
2711: }
2712:
2713: /**
2714: * Set alert message.
2715: * @deprecated
2716: * @param v Value to assign to alertMessage.
2717: */
2718: public void setAlertMessage(Object v) {
2719: this .alertMessage = v;
2720: }
2721:
2722: /**
2723: * Set alert message using Localizable localizable.
2724: * @param v Value to assign to alertMessage.
2725: */
2726: public void setAlertMessage(Localizable localizable) {
2727: ScarabLocalizationTool l10n = getLocalizationTool();
2728: this .alertMessage = new SimpleSkipFiltering(localizable
2729: .getMessage(l10n));
2730: }
2731:
2732: public IssueListIterator getIssueListIterator(
2733: IteratorWithSize iterator, int listOffset, int size) {
2734: return new IssueListIterator(iterator, listOffset, size);
2735: }
2736:
2737: public class IssueListIterator implements Iterator {
2738: private static final String ISSUE_LIST = "issueList";
2739: private static final int PREV_SIZE = 1;
2740: private static final int NEXT_SIZE = 2;
2741:
2742: private WindowIterator i;
2743: private int size;
2744: private int listOffset;
2745: private int count = -1;
2746:
2747: private IssueListIterator(IteratorWithSize iterator,
2748: int listOffset, int size) {
2749: this .listOffset = Math.max(listOffset, 0);
2750: this .size = size;
2751: this .i = new WindowIterator(iterator, PREV_SIZE, NEXT_SIZE);
2752: }
2753:
2754: public Object next() {
2755: count++;
2756: return i.next();
2757: }
2758:
2759: public boolean hasNext() {
2760: return i.hasNext();
2761: }
2762:
2763: public void remove() {
2764: i.remove();
2765: }
2766:
2767: public void initializeLink(ScarabLink link) {
2768: link.setPage("ViewIssue.vm").addPathInfo("id",
2769: ((QueryResult) i.get(0)).getUniqueId());
2770: int offset = listOffset + count;
2771: for (int m = -1 * PREV_SIZE; m < 0; m++) {
2772: if (i.hasValue(m)) {
2773: offset--;
2774: }
2775: }
2776: link.addPathInfo(ISSUE_LIST, offset);
2777: link.addPathInfo(ISSUE_LIST, size);
2778: for (int m = -1 * PREV_SIZE; m <= NEXT_SIZE; m++) {
2779: if (i.hasValue(m)) {
2780: link.addPathInfo(ISSUE_LIST, ((QueryResult) i
2781: .get(m)).getUniqueId());
2782: }
2783: }
2784: }
2785: }
2786:
2787: /**
2788: * @return an IssueType which may represent a template
2789: */
2790: public Object getLastEnteredIssueTypeOrTemplate() throws Exception {
2791: Object result = null;
2792: IssueType issueType = getCurrentIssueType();
2793: ScarabUser user = (ScarabUser) data.getUser();
2794: String templateId = data.getParameters()
2795: .getString("templateId");
2796: if (templateId != null && templateId.trim().length() > 0) {
2797: Issue template = getIssueTemplate(templateId);
2798: issueType = template.getIssueType()
2799: .getIssueTypeForTemplateType();
2800: user.setLastEnteredTemplate(template);
2801: result = template;
2802: }
2803:
2804: if (result == null && issueType != null) {
2805: result = issueType;
2806: user.setLastEnteredIssueType(issueType);
2807: }
2808:
2809: if (result == null) {
2810: result = user.lastEnteredIssueTypeOrTemplate();
2811: if (result != null) {
2812: if (result instanceof Issue) {
2813: issueType = ((Issue) result).getIssueType()
2814: .getIssueTypeForTemplateType();
2815: } else if (result instanceof IssueType) {
2816: issueType = (IssueType) result;
2817: } else {
2818: Log
2819: .get()
2820: .warn(
2821: "An object of unexpected class was saved as"
2822: + " the last entered issue type or template: "
2823: + result.getClass()
2824: .getName());
2825: result = null;
2826: }
2827:
2828: }
2829: }
2830:
2831: // finally if we have a value, check that it is active
2832: if (issueType != null) {
2833: RModuleIssueType rmit = getCurrentModule()
2834: .getRModuleIssueType(issueType);
2835: if (rmit == null || !rmit.getActive()) {
2836: result = null;
2837: }
2838: }
2839:
2840: return result;
2841: }
2842:
2843: public List getSortedAttributeOptions() throws TorqueException {
2844: return AttributeOptionPeer.getSortedAttributeOptions();
2845: }
2846:
2847: /**
2848: * Returned all attribute options allowed for every attribute assigned to this
2849: * RModuleIssueType.
2850: * @param rmit
2851: * @return List with all the attribute options of every attribute.
2852: * @throws Exception
2853: */
2854: public List getSortedAttributeOptionsForRMIT(RModuleIssueType rmit)
2855: throws Exception {
2856: List attributes = rmit.getIssueType().getActiveAttributes(
2857: rmit.getModule());
2858: List result = new ArrayList();
2859: for (Iterator it = attributes.iterator(); it.hasNext();) {
2860: Attribute attr = (Attribute) it.next();
2861: if (attr.getAttributeType().getAttributeClass().getName()
2862: .equals("select-one"))
2863: result.addAll(attr.getAttributeOptions());
2864: }
2865: return result;
2866: }
2867:
2868: /**
2869: * Returns if the system is configurated to allow anonymous login.
2870: *
2871: */
2872: public boolean isAnonymousLoginAllowed() {
2873: return AnonymousUserUtil.anonymousAccessAllowed();
2874: }
2875:
2876: public Transition getTransition(Integer pk) {
2877: Transition tran = null;
2878: try {
2879: tran = TransitionPeer.retrieveByPK(pk);
2880: } catch (Exception e) {
2881: // Nothing to do. Ignore.
2882: }
2883: return tran;
2884: }
2885:
2886: /**
2887: * Returns the list of transitions allowed for the current user
2888: * in the current module/issueType/attribute combination
2889: * @throws TorqueException
2890: */
2891: public List getTransitions(IssueType issueType, Attribute attribute)
2892: throws ScarabException {
2893: ScarabUser user = getCurrentUser();
2894: Workflow workflow = ScarabGlobalTool.getWorkflow();
2895: List result = workflow.getTransitions(user, issueType,
2896: attribute);
2897: return result;
2898: }
2899:
2900: /**
2901: * Returns the list of transitions allowed for the current user
2902: * in the current module/issueType/attribute combination as a displayable
2903: * matrix organized in rows and columns.
2904: * The returned list contains the matrix rows.
2905: * Each row contains a set of OptionValues and OptionConnectors.
2906: *
2907: * An OptionConnector is a hint for a graphical representation and
2908: * can be one of:
2909: * <ul>
2910: * <li>SINGLE or "---" </li>
2911: * <li>FIRST or "-+-" </li>
2912: * <li>INTERMEDIATE or " |-" </li>
2913: * <li>LAST or " +-" </li>
2914: * <li>PASSTHROUGH or " | " </li>
2915: * </ul>
2916: *
2917: * A matrix-The may contain null pointers if there is neither an
2918: * OptionValue nor an OptionConnector associated to the cell. This
2919: * can be seen best in an example (V* denotes OptionValues):
2920: * <p><pre>
2921: * [V1][---][V2][-+-][V3][-+-][V4]
2922: * [ ][ ][ ][ | ][ ][ |-][V5]
2923: * [ ][ ][ ][ | ][ ][ +-][V6]
2924: * [ ][ ][ ][ +-][V7][ ][ ]
2925: * </pre></p>
2926: * If you remove the [] brackets, you should get the idea immediately:
2927: * <p><pre>
2928: * V1---V2-+-V3-+-V4
2929: * | |-V5
2930: * | +-V6
2931: * +-V7
2932: * </pre>
2933: * </p>
2934: * @throws TorqueException
2935: */
2936: public List getTransitionMatrix(IssueType issueType,
2937: Attribute attribute) throws ScarabException {
2938: ScarabUser user = getCurrentUser();
2939: Workflow workflow = ScarabGlobalTool.getWorkflow();
2940: TransitionNode root = workflow.getTransitionTree(user,
2941: issueType, attribute);
2942: List result = root.createRows();
2943: return result;
2944: }
2945:
2946: // ****************** Recyclable implementation ************************
2947: /**
2948: * Recycles the object by removing its disposed flag.
2949: */
2950: public void recycle() {
2951: disposed = false;
2952: }
2953:
2954: /**
2955: * Disposes the object after use. The method is called when the
2956: * object is returned to its pool. The dispose method must call
2957: * its super.
2958: */
2959: public void dispose() {
2960: disposed = true;
2961: data = null;
2962: refresh();
2963: }
2964:
2965: /**
2966: * Checks whether the object is disposed.
2967: *
2968: * @return true, if the object is disposed.
2969: */
2970: public boolean isDisposed() {
2971: return disposed;
2972: }
2973:
2974: /**
2975: * Format a date from internal timestamp value to the user's locale format.
2976: * @param value
2977: * @return
2978: */
2979: public String formatDate(String value) {
2980: return DateAttribute.dateFormat(value, getLocalizationTool()
2981: .get(L10NKeySet.ShortDatePattern));
2982: }
2983:
2984: /**
2985: * Stores in the request scope a type. Used in IssueList.vm
2986: * @param key
2987: * @param type
2988: */
2989: public void setAttributeType(int key, String type) {
2990: attributeTypes.put(Integer.toString(key), type);
2991: }
2992:
2993: /**
2994: * Retrieves an attribute type from request scope. USed in IssueList.vm
2995: * @param key
2996: * @return
2997: */
2998: public String getAttributeType(int key) {
2999: return (String) attributeTypes.get(Integer.toString(key));
3000: }
3001:
3002: public RModuleIssueType getRModuleIssueType(Integer moduleId,
3003: Integer issueTypeId) throws Exception {
3004: return RModuleIssueTypePeer.retrieveByPK(moduleId, issueTypeId);
3005: }
3006:
3007: }
|