001: package org.tigris.scarab.actions.admin;
002:
003: /* ================================================================
004: * Copyright (c) 2000-2002 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: // Java Stuff
050: import java.util.ArrayList;
051: import java.util.Iterator;
052: import java.util.List;
053:
054: import org.apache.fulcrum.intake.model.Group;
055: import org.apache.fulcrum.parser.ParameterParser;
056: import org.apache.torque.TorqueException;
057: import org.apache.torque.om.NumberKey;
058: import org.apache.turbine.RunData;
059: import org.apache.turbine.TemplateContext;
060: import org.apache.turbine.tool.IntakeTool;
061: import org.tigris.scarab.actions.base.RequireLoginFirstAction;
062: import org.tigris.scarab.om.Attribute;
063: import org.tigris.scarab.om.AttributeGroup;
064: import org.tigris.scarab.om.AttributeGroupManager;
065: import org.tigris.scarab.om.AttributeManager;
066: import org.tigris.scarab.om.GlobalParameter;
067: import org.tigris.scarab.om.GlobalParameterManager;
068: import org.tigris.scarab.om.IssueType;
069: import org.tigris.scarab.om.Module;
070: import org.tigris.scarab.om.RAttributeAttributeGroup;
071: import org.tigris.scarab.om.RIssueTypeAttribute;
072: import org.tigris.scarab.om.RModuleAttribute;
073: import org.tigris.scarab.om.RModuleIssueType;
074: import org.tigris.scarab.om.ScarabUser;
075: import org.tigris.scarab.services.cache.ScarabCache;
076: import org.tigris.scarab.services.security.ScarabSecurity;
077: import org.tigris.scarab.tools.ScarabLocalizationTool;
078: import org.tigris.scarab.tools.ScarabRequestTool;
079: import org.tigris.scarab.tools.localization.L10NKeySet;
080: import org.tigris.scarab.tools.localization.LocalizationKey;
081: import org.tigris.scarab.util.Log;
082: import org.tigris.scarab.util.ScarabException;
083: import org.tigris.scarab.util.ScarabLocalizedTorqueException;
084: import org.tigris.scarab.workflow.WorkflowFactory;
085:
086: /**
087: * action methods on RModuleAttribute or RIssueTypeAttribute tables
088: *
089: * @author <a href="mailto:elicia@collab.net">Elicia David</a>
090: * @version $Id: AttributeGroupEdit.java 10221 2006-07-24 08:28:24Z dabbous $
091: */
092: public class AttributeGroupEdit extends RequireLoginFirstAction {
093: /**
094: * Updates attribute group info.
095: */
096: public boolean doSaveinfo(RunData data, TemplateContext context)
097: throws Exception {
098: boolean success = true;
099: // Set properties for group info
100: IntakeTool intake = getIntakeTool(context);
101: ScarabRequestTool scarabR = getScarabRequestTool(context);
102: ScarabLocalizationTool l10n = getLocalizationTool(context);
103: IssueType issueType = scarabR.getIssueType();
104: if (issueType.isSystemDefined()) {
105: scarabR
106: .setAlertMessage(L10NKeySet.SystemSpecifiedIssueType);
107: return false;
108: }
109: String groupId = data.getParameters().getString("groupId");
110: AttributeGroup ag = AttributeGroupManager.getInstance(
111: new NumberKey(groupId), false);
112: Group agGroup = intake.get("AttributeGroup", ag.getQueryKey(),
113: false);
114: if (!ag.isGlobal() && scarabR.getIssueType().getLocked()) {
115: scarabR.setAlertMessage(L10NKeySet.LockedIssueType);
116: return false;
117: }
118: if (intake.isAllValid()) {
119: agGroup.setProperties(ag);
120: ag.save();
121: scarabR.setConfirmMessage(DEFAULT_MSG);
122: } else {
123: success = false;
124: scarabR.setAlertMessage(ERROR_MESSAGE);
125: }
126: return success;
127: }
128:
129: /**
130: * Changes the properties of existing AttributeGroups and their attributes.
131: */
132: public boolean doSaveattributes(RunData data,
133: TemplateContext context) throws Exception {
134: boolean success = true;
135: ScarabRequestTool scarabR = getScarabRequestTool(context);
136: ScarabLocalizationTool l10n = getLocalizationTool(context);
137: IntakeTool intake = getIntakeTool(context);
138: IssueType issueType = scarabR.getIssueType();
139: Module module = scarabR.getCurrentModule();
140:
141: // Check if issue type is system-defined, hence unmodifyable
142: if (issueType.isSystemDefined()) {
143: scarabR
144: .setAlertMessage(L10NKeySet.SystemSpecifiedIssueType);
145: return false;
146: }
147:
148: String groupId = data.getParameters().getString("groupId");
149: AttributeGroup attributeGroup = AttributeGroupManager
150: .getInstance(new NumberKey(groupId), false);
151:
152: LocalizationKey l10nKey = DEFAULT_MSG;
153:
154: // Check if issue type is locked
155: if (!attributeGroup.isGlobal() && issueType.getLocked()) {
156: scarabR.setAlertMessage(L10NKeySet.LockedIssueType);
157: return false;
158: }
159:
160: // Check for duplicate sequence numbers
161: if (areThereDupeSequences(attributeGroup
162: .getRAttributeAttributeGroups(), intake,
163: "RAttributeAttributeGroup", "Order", 0)) {
164: scarabR.setAlertMessage(l10n.format(
165: "DuplicateSequenceNumbersFound", l10n.get(
166: L10NKeySet.Attributes).toLowerCase()));
167: return false;
168: }
169:
170: List rmas = attributeGroup.getRModuleAttributes();
171: ArrayList lockedAttrs = new ArrayList();
172:
173: if (intake.isAllValid()) {
174: // First iterate thru and check for required attributes
175: // That have no active options
176: Iterator i = rmas.iterator();
177: while (i.hasNext()) {
178: RModuleAttribute rma = (RModuleAttribute) i.next();
179: Group rmaGroup = intake.get("RModuleAttribute", rma
180: .getQueryKey(), false);
181: Attribute attr = rma.getAttribute();
182: if (attr.isOptionAttribute()
183: && rmaGroup.get("Required").toString().equals(
184: "true")) {
185: List options = module.getRModuleOptions(rma
186: .getAttribute(), issueType, true);
187: if (options == null || options.isEmpty()) {
188: scarabR
189: .setAlertMessage(L10NKeySet.CannotRequireAttributeWithNoOptions);
190: success = false;
191: }
192: }
193: }
194: if (success) {
195:
196: // Check whether a module specific statusAttribute was selected
197: // and store it in the GLOBAL_PARAMETER table
198: String key = "status_attribute_"
199: + issueType.getIssueTypeId();
200: String statusAttributeKey = data.getParameters()
201: .getString(key);
202: if (statusAttributeKey != null) {
203: String attributeId = GlobalParameterManager
204: .getString(key, module);
205: if (attributeId == null
206: || !attributeId.equals(statusAttributeKey)) {
207: GlobalParameterManager.setString(key, module,
208: statusAttributeKey);
209: }
210: }
211:
212: i = rmas.iterator();
213: while (i.hasNext()) {
214: boolean locked = false;
215: // Set properties for module-attribute mapping
216: RModuleAttribute rma = (RModuleAttribute) i.next();
217: Group rmaGroup = intake.get("RModuleAttribute", rma
218: .getQueryKey(), false);
219: Attribute attr = rma.getAttribute();
220:
221: // Test to see if attribute is locked
222: RModuleAttribute rmaTest = rma.copy();
223: rmaTest.setModified(false);
224: rmaGroup.setProperties(rmaTest);
225: if (rmaTest.isModified()) {
226: RIssueTypeAttribute ria = issueType
227: .getRIssueTypeAttribute(attr);
228: if (ria != null && ria.getLocked()) {
229: lockedAttrs.add(attr);
230: locked = true;
231: }
232: }
233:
234: if (!locked) {
235: // if attribute gets set to inactive, delete dependencies
236: String newActive = rmaGroup.get("Active")
237: .toString();
238: String oldActive = String.valueOf(rma
239: .getActive());
240: if (newActive.equals("false")
241: && oldActive.equals("true")) {
242: WorkflowFactory.getInstance()
243: .deleteWorkflowsForAttribute(attr,
244: module, issueType);
245: }
246: rmaGroup.setProperties(rma);
247: String defaultTextKey = data.getParameters()
248: .getString("default_text");
249: if (defaultTextKey != null
250: && defaultTextKey.equals(rma
251: .getAttributeId().toString())) {
252: if (!rma.getRequired()) {
253: l10nKey = L10NKeySet.ChangesSavedButDefaultTextAttributeRequired;
254: intake.remove(rmaGroup);
255: }
256: rma.setIsDefaultText(true);
257: rma.setRequired(true);
258: }
259:
260: try {
261: rma.save();
262: // Set properties for attribute-attribute group mapping
263: RAttributeAttributeGroup raag = attributeGroup
264: .getRAttributeAttributeGroup(attr);
265: Group raagGroup = intake.get(
266: "RAttributeAttributeGroup", raag
267: .getQueryKey(), false);
268: raagGroup.setProperties(raag);
269: raag.save();
270: scarabR.setConfirmMessage(l10nKey);
271: } catch (ScarabLocalizedTorqueException slte) {
272: String msg = slte.getMessage(l10n);
273: scarabR.setAlertMessage(msg);
274: } catch (TorqueException te) {
275: String msg = te.getMessage();
276: scarabR.setAlertMessage(msg);
277: }
278: }
279:
280: // If they attempted to modify locked attributes, give message.
281: if (lockedAttrs.size() > 0) {
282: setLockedMessage(lockedAttrs, context);
283: }
284: }
285: }
286: } else {
287: success = false;
288: scarabR
289: .setAlertMessage(L10NKeySet.MoreInformationWasRequired);
290: }
291: return success;
292: }
293:
294: /**
295: * Changes the properties of global AttributeGroups and their attributes.
296: */
297: public boolean doSaveglobal(RunData data, TemplateContext context)
298: throws Exception {
299: boolean success = true;
300: IntakeTool intake = getIntakeTool(context);
301: ScarabRequestTool scarabR = getScarabRequestTool(context);
302: ScarabLocalizationTool l10n = getLocalizationTool(context);
303: String groupId = data.getParameters().getString("groupId");
304: AttributeGroup ag = AttributeGroupManager.getInstance(
305: new NumberKey(groupId), false);
306: IssueType issueType = scarabR.getIssueType();
307:
308: // Check if issue type is system defined, hence unmodifyable
309: if (issueType.isSystemDefined()) {
310: scarabR
311: .setAlertMessage(L10NKeySet.SystemSpecifiedIssueType);
312: return false;
313: }
314: if (issueType.getIssueTypeId() == null) {
315: scarabR.setAlertMessage(L10NKeySet.IssueTypeNotFound);
316: return false;
317: }
318:
319: // Check for duplicate sequence numbers
320: if (areThereDupeSequences(ag.getRAttributeAttributeGroups(),
321: intake, "RAttributeAttributeGroup", "Order", 0)) {
322: scarabR.setAlertMessage(l10n.format(
323: "DuplicateSequenceNumbersFound", l10n.get(
324: "Attributes").toLowerCase()));
325: return false;
326: }
327: String l10nMsg = l10n.get(DEFAULT_MSG);
328:
329: if (intake.isAllValid()) {
330: List rias = ag.getRIssueTypeAttributes();
331:
332: // first check if there are required attributes
333: // Without active options
334: Iterator i = rias.iterator();
335: while (i.hasNext()) {
336: RIssueTypeAttribute ria = (RIssueTypeAttribute) i
337: .next();
338: Group riaGroup = intake.get("RIssueTypeAttribute", ria
339: .getQueryKey(), false);
340: Attribute attr = ria.getAttribute();
341: if (attr.isOptionAttribute()
342: && riaGroup.get("Required").toString().equals(
343: "true")) {
344: List options = issueType.getRIssueTypeOptions(ria
345: .getAttribute(), true);
346: if (options == null || options.isEmpty())
347: if (issueType.getRIssueTypeOptions(attr, true)
348: .isEmpty()) {
349: scarabR
350: .setAlertMessage(L10NKeySet.CannotRequireAttributeWithNoOptions);
351: success = false;
352: }
353: }
354: }
355: i = rias.iterator();
356: if (success) {
357: while (i.hasNext()) {
358: RIssueTypeAttribute ria = (RIssueTypeAttribute) i
359: .next();
360: Group riaGroup = intake.get("RIssueTypeAttribute",
361: ria.getQueryKey(), false);
362: riaGroup.setProperties(ria);
363: String defaultTextKey = data.getParameters()
364: .getString("default_text");
365: if (defaultTextKey != null
366: && defaultTextKey.equals(ria
367: .getAttributeId().toString())) {
368: if (!ria.getRequired()) {
369: l10nMsg = l10n
370: .get(L10NKeySet.ChangesSavedButDefaultTextAttributeRequired);
371: }
372: ria.setIsDefaultText(true);
373: ria.setRequired(true);
374: intake.remove(riaGroup);
375: }
376: ria.save();
377:
378: // Set properties for attribute-attribute group mapping
379: RAttributeAttributeGroup raag = ag
380: .getRAttributeAttributeGroup(ria
381: .getAttribute());
382: Group raagGroup = intake.get(
383: "RAttributeAttributeGroup", raag
384: .getQueryKey(), false);
385: raagGroup.setProperties(raag);
386: raag.save();
387: }
388: scarabR.setConfirmMessage(l10nMsg);
389: }
390: } else {
391: success = false;
392: scarabR.setAlertMessage(l10nMsg);
393: }
394: return success;
395: }
396:
397: /**
398: * Unmaps attributes to modules.
399: */
400: public void doDeleteattributes(RunData data, TemplateContext context)
401: throws Exception {
402: ScarabRequestTool scarabR = getScarabRequestTool(context);
403: ScarabLocalizationTool l10n = getLocalizationTool(context);
404: Module module = scarabR.getCurrentModule();
405: IssueType issueType = scarabR.getIssueType();
406: if (issueType.isSystemDefined()) {
407: scarabR
408: .setAlertMessage(L10NKeySet.SystemSpecifiedIssueType);
409: return;
410: }
411: ScarabUser user = (ScarabUser) data.getUser();
412: String groupId = data.getParameters().getString("groupId");
413: AttributeGroup ag = AttributeGroupManager.getInstance(
414: new NumberKey(groupId), false);
415: boolean hasAttributes = false;
416:
417: if (!user.hasPermission(ScarabSecurity.MODULE__EDIT, module)) {
418: scarabR.setAlertMessage(NO_PERMISSION_MESSAGE);
419: return;
420: }
421: if (!ag.isGlobal() && issueType.getLocked()) {
422: scarabR.setAlertMessage(L10NKeySet.LockedIssueType);
423: return;
424: }
425: ParameterParser params = data.getParameters();
426: Object[] keys = params.getKeys();
427: String key;
428: String attributeId;
429: ArrayList lockedAttrs = new ArrayList();
430:
431: for (int i = 0; i < keys.length; i++) {
432: key = keys[i].toString();
433: if (key.startsWith("att_delete_")) {
434: hasAttributes = true;
435: attributeId = key.substring(11);
436: Attribute attribute = AttributeManager.getInstance(
437: new NumberKey(attributeId), false);
438: RIssueTypeAttribute ria = issueType
439: .getRIssueTypeAttribute(attribute);
440: if (!ag.isGlobal() && ria != null && ria.getLocked()) {
441: lockedAttrs.add(attribute);
442: } else {
443: try {
444: ag.deleteAttribute(attribute, user, module);
445: } catch (ScarabException e) {
446: scarabR.setAlertMessage(l10n.getMessage(e));
447: Log
448: .get()
449: .warn(
450: "This is an application error, if it is not permission related.",
451: e);
452: }
453: }
454: }
455: }
456: if (!hasAttributes) {
457: scarabR.setAlertMessage(L10NKeySet.NoAttributeSelected);
458: }
459:
460: // If there are no attributes in any of the dedupe
461: // Attribute groups, turn off deduping in the module
462: boolean areThereDedupeAttrs = false;
463: List attributeGroups = issueType.getAttributeGroups(module,
464: true);
465: if (attributeGroups.size() > 0) {
466: for (int j = 0; j < attributeGroups.size(); j++) {
467: AttributeGroup agTemp = (AttributeGroup) attributeGroups
468: .get(j);
469: if (agTemp.getDedupe()
470: && !agTemp.getAttributes().isEmpty()) {
471: areThereDedupeAttrs = true;
472: }
473: }
474: if (!areThereDedupeAttrs) {
475: if (module == null) {
476: issueType.setDedupe(false);
477: issueType.save();
478: } else {
479: RModuleIssueType rmit = module
480: .getRModuleIssueType(issueType);
481: rmit.setDedupe(false);
482: rmit.save();
483: }
484: }
485: }
486:
487: // If they attempted to modify locked attributes, give message.
488: if (lockedAttrs.size() > 0) {
489: setLockedMessage(lockedAttrs, context);
490: }
491: ScarabCache.clear();
492: if (hasAttributes) {
493: scarabR.setConfirmMessage(DEFAULT_MSG);
494: }
495: }
496:
497: /**
498: * This manages clicking the create new button on AttributeSelect.vm
499: */
500: public void doCreatenewglobalattribute(RunData data,
501: TemplateContext context) throws Exception {
502: IntakeTool intake = getIntakeTool(context);
503: ScarabRequestTool scarabR = getScarabRequestTool(context);
504: IssueType issueType = scarabR.getIssueType();
505: if (issueType.isSystemDefined()) {
506: scarabR
507: .setAlertMessage(L10NKeySet.SystemSpecifiedIssueType);
508: return;
509: }
510: Group attGroup = intake
511: .get("Attribute", IntakeTool.DEFAULT_KEY);
512: intake.remove(attGroup);
513: scarabR.setAttribute(null);
514: setTarget(data, getOtherTemplate(data));
515: }
516:
517: /**
518: * Selects attribute to add to issue type and attribute group.
519: */
520: public void doSelectattribute(RunData data, TemplateContext context)
521: throws Exception {
522: ScarabRequestTool scarabR = getScarabRequestTool(context);
523: ScarabLocalizationTool l10n = getLocalizationTool(context);
524: IssueType issueType = scarabR.getIssueType();
525: if (issueType.isSystemDefined()) {
526: scarabR
527: .setAlertMessage(L10NKeySet.SystemSpecifiedIssueType);
528: return;
529: }
530: AttributeGroup ag = scarabR.getAttributeGroup();
531:
532: if (!ag.isGlobal() && scarabR.getIssueType().getLocked()) {
533: scarabR.setAlertMessage(L10NKeySet.LockedIssueType);
534: return;
535: }
536: String[] attributeIds = data.getParameters().getStrings(
537: "attribute_ids");
538:
539: if (attributeIds == null || attributeIds.length <= 0) {
540: scarabR.setAlertMessage(L10NKeySet.SelectAttribute);
541: return;
542: } else {
543: boolean alreadySubmited = false;
544: for (int i = 0; i < attributeIds.length; i++) {
545: Attribute attribute = scarabR.getAttribute(new Integer(
546: attributeIds[i]));
547: try {
548: ag.addAttribute(attribute);
549: } catch (TorqueException e) {
550: alreadySubmited = true;
551: scarabR.setAlertMessage(L10NKeySet.ResubmitError);
552: }
553: }
554: doCancel(data, context);
555: if (!alreadySubmited) {
556: scarabR.setConfirmMessage(DEFAULT_MSG);
557: }
558: }
559: }
560:
561: /**
562: * Saves all data when Done is clicked.
563: */
564: public void doDone(RunData data, TemplateContext context)
565: throws Exception {
566: String groupId = data.getParameters().getString("groupId");
567: AttributeGroup ag = AttributeGroupManager.getInstance(
568: new NumberKey(groupId), false);
569: boolean infoSuccess = doSaveinfo(data, context);
570: boolean attrSuccess = false;
571: if (ag.isGlobal()) {
572: attrSuccess = doSaveglobal(data, context);
573: } else {
574: attrSuccess = doSaveattributes(data, context);
575: }
576: if (infoSuccess && attrSuccess) {
577: doCancel(data, context);
578: }
579: }
580:
581: /**
582: * If user attempts to modify locked attributes, gives message.
583: */
584: private void setLockedMessage(List lockedAttrs,
585: TemplateContext context) throws Exception {
586: StringBuffer buf = new StringBuffer();
587: for (int i = 0; i < lockedAttrs.size(); i++) {
588: Attribute attr = (Attribute) lockedAttrs.get(i);
589: buf.append(attr.getName());
590: if (i == lockedAttrs.size() - 1) {
591: buf.append(".");
592: } else {
593: buf.append(",");
594: }
595: }
596: getScarabRequestTool(context).setAlertMessage(
597: getLocalizationTool(context).format("LockedAttributes",
598: buf.toString()));
599: }
600: }
|