001: package org.tigris.scarab.om;
002:
003: /* ================================================================
004: * Copyright (c) 2000-2005 CollabNet. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are
008: * met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowlegement: "This product includes
019: * software developed by Collab.Net <http://www.Collab.Net/>."
020: * Alternately, this acknowlegement may appear in the software itself, if
021: * and wherever such third-party acknowlegements normally appear.
022: *
023: * 4. The hosted project names must not be used to endorse or promote
024: * products derived from this software without prior written
025: * permission. For written permission, please contact info@collab.net.
026: *
027: * 5. Products derived from this software may not use the "Tigris" or
028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
029: * prior written permission of Collab.Net.
030: *
031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042: *
043: * ====================================================================
044: *
045: * This software consists of voluntary contributions made by many
046: * individuals on behalf of Collab.Net.
047: */
048:
049: import java.util.List;
050: import java.util.Arrays;
051: import java.util.Date;
052:
053: import org.apache.turbine.TemplateContext;
054: import org.apache.turbine.Turbine;
055:
056: import org.apache.torque.TorqueException;
057: import org.apache.torque.util.Criteria;
058: import org.apache.torque.om.Persistent;
059:
060: import org.tigris.scarab.services.security.ScarabSecurity;
061: import org.tigris.scarab.services.cache.ScarabCache;
062: import org.tigris.scarab.tools.localization.L10NKeySet;
063: import org.tigris.scarab.om.Module;
064: import org.tigris.scarab.om.ModuleManager;
065: import org.tigris.scarab.util.ScarabException;
066: import org.tigris.scarab.util.Email;
067: import org.tigris.scarab.util.EmailContext;
068: import org.tigris.scarab.util.Log;
069:
070: /**
071: * This class manages the Query table.
072: *
073: * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
074: * @version $Id: Query.java 9977 2005-12-09 00:40:59Z hair $
075: */
076: public class Query extends BaseQuery implements Persistent {
077: private static final String GET_R_QUERY_USER = "getRQueryUser";
078:
079: /**
080: * A local reference, so that getScarabUser is guaranteed to return
081: * the same instance as was passed to setScarabUser
082: */
083: private ScarabUser scarabUser;
084:
085: /**
086: * Get the value of scarabUser.
087: * @return value of scarabUser.
088: */
089: public ScarabUser getScarabUser() throws TorqueException {
090: ScarabUser user = this .scarabUser;
091: if (user == null) {
092: user = super .getScarabUser();
093: }
094:
095: return user;
096: }
097:
098: /**
099: * Set the value of scarabUser.
100: * @param v Value to assign to scarabUser.
101: */
102: public void setScarabUser(ScarabUser v) throws TorqueException {
103: this .scarabUser = v;
104: super .setScarabUser(v);
105: }
106:
107: /**
108: * Throws UnsupportedOperationException. Use
109: * <code>getModule()</code> instead.
110: *
111: * @return a <code>ScarabModule</code> value
112: */
113: public ScarabModule getScarabModule() {
114: throw new UnsupportedOperationException("Should use getModule"); //EXCEPTION
115: }
116:
117: /**
118: * Throws UnsupportedOperationException. Use
119: * <code>setModule(Module)</code> instead.
120: *
121: */
122: public void setScarabModule(ScarabModule module) {
123: throw new UnsupportedOperationException(
124: "Should use setModule(Module). Note module cannot be new."); //EXCEPTION
125: }
126:
127: /**
128: * Use this instead of setScarabModule. Note: module cannot be new.
129: */
130: public void setModule(Module me) throws TorqueException {
131: if (me == null) {
132: setModuleId((Integer) null);
133: } else {
134: Integer id = me.getModuleId();
135: if (id == null) {
136: throw new TorqueException(
137: "Modules must be saved prior to "
138: + "being associated with other objects."); //EXCEPTION
139: }
140: setModuleId(id);
141: }
142: }
143:
144: /**
145: * Module getter. Use this method instead of getScarabModule().
146: *
147: * @return a <code>Module</code> value
148: */
149: public Module getModule() throws TorqueException {
150: Module module = null;
151: Integer id = getModuleId();
152: if (id != null) {
153: module = ModuleManager.getInstance(id);
154: }
155:
156: return module;
157: }
158:
159: /**
160: * A new Query object
161: */
162: public static Query getInstance() {
163: return new Query();
164: }
165:
166: public boolean canDelete(ScarabUser user) throws TorqueException {
167: // can delete a query if they have delete permission
168: // Or if is their personal query
169: return (user.hasPermission(ScarabSecurity.ITEM__DELETE,
170: getModule()) || (user.getUserId().equals(getUserId()) && (getScopeId()
171: .equals(Scope.PERSONAL__PK))));
172: }
173:
174: public boolean canEdit(ScarabUser user) throws TorqueException {
175: return canDelete(user);
176: }
177:
178: /**
179: * Either returns true, if no email problem occured,
180: * or throws an appropriate Exception. Note: If an email
181: * exception occured, the query is still saved.
182: * @param user
183: * @param module
184: * @param context
185: * @return
186: * @throws TorqueException
187: */
188: public boolean saveAndSendEmail(final ScarabUser user,
189: final Module module, final TemplateContext context)
190: throws TorqueException, ScarabException {
191: // If it's a module scoped query, user must have Item | Approve
192: // permission, Or its Approved field gets set to false
193: Exception exception = null; // temporary store a thrown exception
194:
195: if (getScopeId().equals(Scope.PERSONAL__PK)
196: || user.hasPermission(ScarabSecurity.ITEM__APPROVE,
197: module)) {
198: setApproved(true);
199: } else {
200: setApproved(false);
201:
202: // Send Email to the people with module edit ability so
203: // that they can approve the new template
204: if (context != null) {
205: final String template = Turbine
206: .getConfiguration()
207: .getString(
208: "scarab.email.requireapproval.template",
209: "RequireApproval.vm");
210:
211: final ScarabUser[] toUsers = module
212: .getUsers(ScarabSecurity.ITEM__APPROVE);
213:
214: if (Log.get().isDebugEnabled()) {
215: if (toUsers == null || toUsers.length == 0) {
216: Log.get().debug("No users to approve query.");
217: } else {
218: Log.get().debug("Users to approve query: ");
219: for (int i = 0; i < toUsers.length; i++) {
220: Log.get().debug(toUsers[i].getEmail());
221: }
222: }
223: }
224:
225: final EmailContext ectx = new EmailContext();
226: ectx.setUser(user);
227: ectx.setModule(module);
228: ectx.setDefaultTextKey("NewQueryRequiresApproval");
229:
230: final String fromUser = "scarab.email.default";
231: try {
232: Email.sendEmail(ectx, module, fromUser, module
233: .getSystemEmail(), Arrays.asList(toUsers),
234: null, template);
235: } catch (Exception e) {
236: exception = e;
237: }
238: }
239: }
240: if (getMITList() != null) {
241: getMITList().save();
242: // it would be good if this updated our list id, but it doesn't
243: // happen automatically so reset it.
244: setMITList(getMITList());
245: }
246: save();
247: if (exception != null) {
248: throw new ScarabException(L10NKeySet.ExceptionGeneral,
249: exception);
250: }
251: return true;
252: }
253:
254: public MITList getMITList() throws TorqueException {
255: MITList mitlist = super .getMITList();
256: if (mitlist == null) {
257: mitlist = MITListManager.getSingleItemList(getModule(),
258: getIssueType(), null);
259: }
260: return mitlist;
261: }
262:
263: /**
264: * Subscribes user to query.
265: */
266: public void subscribe(ScarabUser user, Integer frequencyId)
267: throws TorqueException {
268: RQueryUser rqu = getRQueryUser(user);
269: rqu.setSubscriptionFrequency(frequencyId);
270: rqu.setIsSubscribed(true);
271: rqu.save();
272: }
273:
274: /**
275: * Unsubscribes user from query.
276: */
277: public void unSubscribe(ScarabUser user) throws TorqueException {
278: RQueryUser rqu = getRQueryUser(user);
279: if (rqu.getIsdefault()) {
280: rqu.setIsSubscribed(false);
281: rqu.save();
282: } else {
283: rqu.delete(user);
284: }
285: }
286:
287: /**
288: * Gets RQueryUser object for this query and user.
289: */
290: public RQueryUser getRQueryUser(ScarabUser user)
291: throws TorqueException {
292: RQueryUser result = null;
293: Object obj = ScarabCache.get(this , GET_R_QUERY_USER, user);
294: if (obj == null) {
295: Criteria crit = new Criteria();
296: crit.add(RQueryUserPeer.QUERY_ID, getQueryId());
297: crit.add(RQueryUserPeer.USER_ID, user.getUserId());
298: List rqus = RQueryUserPeer.doSelect(crit);
299: if (!rqus.isEmpty()) {
300: result = (RQueryUser) rqus.get(0);
301: } else {
302: result = new RQueryUser();
303: result.setQuery(this );
304: result.setUserId(user.getUserId());
305: }
306: ScarabCache.put(result, this , GET_R_QUERY_USER, user);
307: } else {
308: result = (RQueryUser) obj;
309: }
310: return result;
311: }
312:
313: /**
314: * Checks permission and approves or rejects query. If query
315: * is approved, query type set to "module", else set to "personal".
316: */
317: public void approve(final ScarabUser user, final boolean approved)
318: throws TorqueException, ScarabException {
319: final Module module = getModule();
320:
321: if (user.hasPermission(ScarabSecurity.ITEM__APPROVE, module)) {
322: setApproved(true);
323: if (!approved) {
324: setScopeId(Scope.PERSONAL__PK);
325: }
326: save();
327: } else {
328: throw new ScarabException(
329: L10NKeySet.YouDoNotHavePermissionToAction);
330: }
331: }
332:
333: /**
334: * Checks if user has permission to delete query.
335: * Only the creating user can delete a personal query.
336: * Only project owner or admin can delete a project-wide query.
337: */
338: public void delete(ScarabUser user) throws TorqueException,
339: ScarabException {
340: final Module module = getModule();
341: if (user.hasPermission(ScarabSecurity.ITEM__APPROVE, module)
342: || (user.getUserId().equals(getUserId()) && getScopeId()
343: .equals(Scope.PERSONAL__PK))) {
344: // Delete user-query maps.
345: final List rqus = getRQueryUsers();
346: for (int i = 0; i < rqus.size(); i++) {
347: final RQueryUser rqu = (RQueryUser) rqus.get(i);
348: rqu.delete(user);
349: }
350: setDeleted(true);
351: save();
352:
353: } else {
354: throw new ScarabException(
355: L10NKeySet.YouDoNotHavePermissionToAction);
356: }
357: }
358:
359: /**
360: * Checks if user has permission to delete query.
361: * Only the creating user can delete a personal query.
362: * Only project owner or admin can delete a project-wide query.
363: */
364: public void copyQuery(ScarabUser user) throws TorqueException {
365: Query newQuery = new Query();
366: newQuery.setName(getName() + " (copy)");
367: newQuery.setDescription(getDescription());
368: newQuery.setValue(getValue());
369: newQuery.setModuleId(getModuleId());
370: newQuery.setIssueTypeId(getIssueTypeId());
371: newQuery.setListId(getListId());
372: newQuery.setApproved(getApproved());
373: newQuery.setCreatedDate(new Date());
374: newQuery.setUserId(user.getUserId());
375: newQuery.setScopeId(getScopeId());
376: newQuery.save();
377:
378: RQueryUser rqu = getRQueryUser(user);
379: if (rqu != null) {
380: RQueryUser rquNew = new RQueryUser();
381: rquNew.setQueryId(newQuery.getQueryId());
382: rquNew.setUserId(user.getUserId());
383: rquNew.setSubscriptionFrequency(rqu
384: .getSubscriptionFrequency());
385: rquNew.setIsdefault(rqu.getIsdefault());
386: rquNew.setIsSubscribed(rqu.getIsSubscribed());
387: rquNew.save();
388: }
389: }
390: }
|