KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > tigris > scarab > om > AbstractScarabModule


1 package org.tigris.scarab.om;
2
3 /* ================================================================
4  * Copyright (c) 2000-2002 CollabNet. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowlegement: "This product includes
19  * software developed by Collab.Net <http://www.Collab.Net/>."
20  * Alternately, this acknowlegement may appear in the software itself, if
21  * and wherever such third-party acknowlegements normally appear.
22  *
23  * 4. The hosted project names must not be used to endorse or promote
24  * products derived from this software without prior written
25  * permission. For written permission, please contact info@collab.net.
26  *
27  * 5. Products derived from this software may not use the "Tigris" or
28  * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
29  * prior written permission of Collab.Net.
30  *
31  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
32  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
35  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
37  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
39  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  *
43  * ====================================================================
44  *
45  * This software consists of voluntary contributions made by many
46  * individuals on behalf of Collab.Net.
47  */

48
49 // JDK classes
50
import java.util.List JavaDoc;
51 import java.util.Iterator JavaDoc;
52 import java.util.LinkedList JavaDoc;
53 import java.util.Collections JavaDoc;
54 import java.util.ArrayList JavaDoc;
55 import java.util.Map JavaDoc;
56 import java.util.HashMap JavaDoc;
57 import java.util.Locale JavaDoc;
58 import java.util.Vector JavaDoc;
59
60 import org.apache.regexp.RECompiler;
61 import org.apache.regexp.REProgram;
62 import org.apache.regexp.RESyntaxException;
63 import com.workingdogs.village.Record;
64
65 // Turbine classes
66
import org.apache.torque.NoRowsException;
67 import org.apache.torque.TorqueException;
68 import org.apache.torque.om.ComboKey;
69 import org.apache.torque.om.SimpleKey;
70 import org.apache.torque.om.BaseObject;
71 import org.apache.torque.manager.MethodResultCache;
72 import org.apache.torque.util.Criteria;
73 import org.apache.fulcrum.security.entity.Group;
74 import org.apache.fulcrum.localization.Localization;
75 import org.apache.turbine.Turbine;
76
77 // Scarab classes
78
import org.tigris.scarab.tools.localization.L10NKeySet;
79 import org.tigris.scarab.tools.localization.L10NMessage;
80 import org.tigris.scarab.tools.localization.Localizable;
81 import org.tigris.scarab.util.ScarabException;
82 import org.tigris.scarab.util.ValidationException;
83 import org.tigris.scarab.util.ScarabConstants;
84 import org.tigris.scarab.services.security.ScarabSecurity;
85 import org.tigris.scarab.services.cache.ScarabCache;
86 import org.tigris.scarab.workflow.WorkflowFactory;
87 import org.tigris.scarab.reports.ReportBridge;
88
89 /**
90  * <p>
91  * The ScarabModule class is the focal point for dealing with
92  * Modules. It implements the concept of a Module which is a
93  * single module and is the base interface for all Modules. In code,
94  * one should <strong>never reference ScarabModule directly</strong>
95  * -- use its Module interface instead. This allows us to swap
96  * out Module implementations by modifying the Scarab.properties
97  * file.
98  * </p>
99  *
100  * <p>This class is the base class for
101  * <code>org.tigris.scarab.om.ScarabModule</code>. BaseScarabModule extends
102  * this class and that definition is defined in the scarab-schema.xml
103  * which is used by Torque to generated BaseScarabModule.</p>
104  *
105  * @author <a HREF="mailto:jon@collab.net">Jon S. Stevens</a>
106  * @author <a HREF="mailto:jmcnally@collab.net">John McNally</a>
107  * @version $Id: AbstractScarabModule.java 9378 2005-01-06 21:03:55Z dabbous $
108  */

109 public abstract class AbstractScarabModule
110     extends BaseObject
111     implements Module, Comparable JavaDoc
112 {
113     private static int moduleCodeLength;
114     // the following Strings are method names that are used in caching results
115
protected static final String JavaDoc GET_R_MODULE_ATTRIBUTES =
116         "getRModuleAttributes";
117     protected static final String JavaDoc GET_DEDUPE_GROUPS_WITH_ATTRIBUTES =
118         "getDedupeGroupsWithAttributes";
119     protected static final String JavaDoc GET_SAVED_REPORTS =
120         "getSavedReports";
121     protected static final String JavaDoc GET_DEFAULT_RMODULE_USERATTRIBUTES =
122         "getDefaultRModuleUserAttributes";
123     protected static final String JavaDoc GET_ISSUE_TYPES =
124         "getIssueTypes";
125     protected static final String JavaDoc GET_NAV_ISSUE_TYPES =
126         "getNavIssueTypes";
127     protected static final String JavaDoc GET_ALL_R_MODULE_OPTIONS =
128         "getAllRModuleOptions";
129     protected static final String JavaDoc GET_LEAF_R_MODULE_OPTIONS =
130         "getLeafRModuleOptions";
131     protected static final String JavaDoc GET_R_MODULE_ISSUE_TYPES =
132         "getRModuleIssueTypes";
133     protected static final String JavaDoc GET_R_MODULE_ISSUE_TYPE =
134         "getRModuleIssueType";
135     protected static final String JavaDoc GET_TEMPLATE_TYPES =
136         "getTemplateTypes";
137     protected static final String JavaDoc GET_UNAPPROVED_QUERIES =
138         "getUnapprovedQueries";
139     protected static final String JavaDoc GET_UNAPPROVED_TEMPLATES =
140         "getUnapprovedTemplates";
141     protected static final String JavaDoc GET_AVAILABLE_ISSUE_TYPES =
142         "getAvailableIssueTypes";
143
144     private List JavaDoc parentModules = null;
145
146     /** set to true while the setInitialAttributesAndIssueTypes() method is in process */
147     private boolean isInitializing = false;
148
149     /**
150      * Should be called when the parentage is modified.
151      */

152     protected void resetAncestors()
153     {
154         parentModules = null;
155     }
156
157     /**
158      * The 'long' name of the module, includes the parents.
159      */

160     private String JavaDoc name = null;
161
162     /**
163      * @see org.tigris.scarab.om.Module#getUsers(String)
164      */

165     public abstract ScarabUser[] getUsers(String JavaDoc permission)
166         throws Exception JavaDoc;
167
168     /**
169      * @see org.tigris.scarab.om.Module#getUsers(String)
170      */

171     public abstract ScarabUser[] getUsers(List JavaDoc permissions)
172         throws Exception JavaDoc;
173
174     /**
175      * @return The unadorned real name of this module; never
176      * <code>null</code>.
177      * @see #getName()
178      */

179     public abstract String JavaDoc getRealName();
180
181     public abstract Integer JavaDoc getModuleId();
182
183     /**
184      * This method is an implementation of the Group.getName() method
185      * and returns a module along with its ancestors
186      */

187     public String JavaDoc getName()
188     {
189         if (name == null)
190         {
191             boolean isRoot = getModuleId().equals(ROOT_ID);
192             if (isRoot)
193             {
194                 return getRealName();
195             }
196             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
197             List JavaDoc parents = null;
198             try
199             {
200                 parents = getAncestors();
201             }
202             catch (Exception JavaDoc e)
203             {
204                 e.printStackTrace();
205                 getLog().error(e);
206                 return null;
207             }
208             Iterator JavaDoc itr = parents.iterator();
209             boolean firstTime = true;
210             while (itr.hasNext())
211             {
212                 Module me = (Module) itr.next();
213                 if (!firstTime)
214                 {
215                     sb.append(Module.NAME_DELIMINATOR);
216                 }
217                 sb.append(me.getRealName());
218                 firstTime = false;
219             }
220             // Make sure we have parents and if we are root,
221
// don't show ourselves again.
222
if (parents.size() >= 1 && !isRoot)
223             {
224                 sb.append(Module.NAME_DELIMINATOR);
225             }
226             // If we are root, don't show ourselves again.
227
if (!isRoot)
228             {
229                 sb.append(getRealName());
230             }
231             name = sb.toString();
232         }
233         return name;
234     }
235
236     /**
237      * This method is an implementation of the Group.setName() method
238      */

239     public void setName(String JavaDoc name)
240     {
241         this.name = name;
242     }
243
244     /**
245      * Creates a new Issue.
246      */

247     public Issue getNewIssue(IssueType issueType)
248         throws Exception JavaDoc
249     {
250         Issue issue = Issue.getNewInstance(this, issueType);
251         issue.setDeleted(false);
252         return issue;
253     }
254
255     /**
256      * Returns this ModuleEntities ancestors in ascending order.
257      * It does not return the 0 parent though.
258      */

259     public synchronized List JavaDoc getAncestors()
260         throws Exception JavaDoc
261     {
262         if (parentModules == null)
263         {
264             parentModules = new ArrayList JavaDoc();
265             Module parent = getParent();
266             if (parent != null && !isEndlessLoop(parent))
267             {
268                 addAncestors(parent);
269             }
270         }
271         return parentModules;
272     }
273
274     /**
275      * recursive helper method for getAncestors()
276      */

277     private void addAncestors(Module module)
278         throws Exception JavaDoc
279     {
280         if (!module.getParentId().equals(ROOT_ID))
281         {
282             addAncestors(module.getParent());
283         }
284         parentModules.add(module);
285     }
286
287     /**
288      * check for endless loops where Module A > Module B > Module A
289      */

290     public boolean isEndlessLoop(Module parent)
291         throws Exception JavaDoc
292     {
293         if (parent.getModuleId() != ROOT_ID)
294         {
295             Module parentParent = parent.getParent();
296             if (parentParent != null && parentParent == this)
297             {
298                 return true;
299             }
300         }
301         return false;
302     }
303
304     /**
305      * Creates new attribute group.
306      */

307     public AttributeGroup createNewGroup (IssueType issueType)
308         throws Exception JavaDoc
309     {
310         return issueType.createNewGroup(this);
311     }
312
313     /**
314      * This method is used within Wizard1.vm to get a list of attribute
315      * groups which are marked as dedupe and have a list of attributes
316      * in them.
317      */

318     public List JavaDoc getDedupeGroupsWithAttributes(IssueType issueType)
319         throws Exception JavaDoc
320     {
321         List JavaDoc result = null;
322         if(issueType == null)
323         {
324             result = new Vector JavaDoc(0);
325         }
326         else
327         {
328             Object JavaDoc obj = getMethodResult().get(this,
329                     GET_DEDUPE_GROUPS_WITH_ATTRIBUTES, issueType);
330             if (obj == null)
331             {
332                 List JavaDoc attributeGroups = issueType.getAttributeGroups(this, true);
333                 result = new ArrayList JavaDoc(attributeGroups.size());
334                 for (Iterator JavaDoc itr = attributeGroups.iterator(); itr.hasNext();)
335                 {
336                     AttributeGroup ag = (AttributeGroup) itr.next();
337                     if (ag.getDedupe() && !ag.getAttributes().isEmpty())
338                     {
339                         result.add(ag);
340                     }
341                 }
342                 getMethodResult().put(result, this,
343                         GET_DEDUPE_GROUPS_WITH_ATTRIBUTES, issueType);
344             }
345             else
346             {
347                 result = (List JavaDoc) obj;
348             }
349         }
350         return result;
351     }
352
353
354     /**
355      * List of active dedupe attribute groups associated with this module.
356      */

357     public List JavaDoc getDedupeAttributeGroups(IssueType issueType)
358         throws Exception JavaDoc
359     {
360         return getDedupeAttributeGroups(issueType, true);
361     }
362
363     /**
364      * List of attribute groups associated with this module.
365      */

366     public List JavaDoc getDedupeAttributeGroups(IssueType issueType,
367                                          boolean activeOnly)
368         throws Exception JavaDoc
369     {
370         List JavaDoc groups = issueType.getAttributeGroups(this, activeOnly);
371         List JavaDoc dedupeGroups = new ArrayList JavaDoc();
372         for (int i =0;i< groups.size(); i++)
373         {
374             AttributeGroup group = (AttributeGroup)groups.get(i);
375             if (group.getDedupe())
376             {
377                 dedupeGroups.add(group);
378             }
379         }
380         return dedupeGroups;
381     }
382
383     /**
384      * Gets the sequence where the dedupe screen fits between groups.
385      */

386     public int getDedupeSequence(IssueType issueType)
387         throws Exception JavaDoc
388     {
389         return issueType.getDedupeSequence(this);
390     }
391
392     public ScarabUser[] getEligibleIssueReporters()
393         throws Exception JavaDoc
394     {
395         return getUsers(ScarabSecurity.ISSUE__ENTER);
396     }
397
398     /**
399      * The users who are possible candidates as values for the given
400      * attribute. An eligible user is determined by checking for users that
401      * have the permission associated with the attribute.
402      *
403      * @param attribute an <code>Attribute</code> value
404      * @return a <code>ScarabUser[]</code> value
405      * @exception ScarabException if the attribute has no associated permission
406      * @exception Exception if an error occurs
407      */

408     public ScarabUser[] getEligibleUsers(Attribute attribute)
409         throws Exception JavaDoc
410     {
411         ScarabUser[] users = null;
412         if (attribute.isUserAttribute())
413         {
414             String JavaDoc permission = attribute.getPermission();
415             if (permission == null)
416             {
417                 throw new ScarabException(
418                         L10NKeySet.ExceptionNoAttributePermission,
419                         attribute.getName());
420             }
421             else
422             {
423                 users = getUsers(permission);
424             }
425         }
426         return users;
427     }
428
429     /**
430      * Set this module's immediate parent module
431      */

432     public abstract void setParent(Module v)
433         throws Exception JavaDoc;
434
435     /**
436      * Get this module's immediate parent module
437      */

438     public abstract Module getParent()
439         throws Exception JavaDoc;
440
441
442     /**
443      * List of saved reports associated with this module and
444      * created by this user.
445      */

446     public List JavaDoc getSavedReports(ScarabUser user)
447         throws Exception JavaDoc
448     {
449         List JavaDoc reports = null;
450         Object JavaDoc obj = ScarabCache.get(this, GET_SAVED_REPORTS, user);
451         if (obj == null)
452         {
453             Criteria crit = new Criteria()
454                 .add(ReportPeer.DELETED, 0);
455             Criteria.Criterion cc = crit.getNewCriterion(
456                 ReportPeer.SCOPE_ID, Scope.MODULE__PK, Criteria.EQUAL);
457             cc.and(crit.getNewCriterion(
458                 ReportPeer.MODULE_ID, getModuleId(), Criteria.EQUAL));
459             Criteria.Criterion personalcc = crit.getNewCriterion(
460                 ReportPeer.SCOPE_ID, Scope.PERSONAL__PK, Criteria.EQUAL);
461             personalcc.and(crit.getNewCriterion(
462                 ReportPeer.USER_ID, user.getUserId(), Criteria.EQUAL));
463             Criteria.Criterion personalmodulecc = crit.getNewCriterion(
464                 ReportPeer.MODULE_ID, getModuleId(), Criteria.EQUAL);
465             personalmodulecc.or(crit.getNewCriterion(
466                 ReportPeer.MODULE_ID, null, Criteria.EQUAL));
467             personalcc.and(personalmodulecc);
468             cc.or(personalcc);
469             crit.add(cc);
470             crit.addAscendingOrderByColumn(ReportPeer.SCOPE_ID);
471             List JavaDoc torqueReports = ReportPeer.doSelect(crit);
472             // create ReportBridge's from torque Reports.
473
if (!torqueReports.isEmpty())
474             {
475                 reports = new ArrayList JavaDoc(torqueReports.size());
476                 for (Iterator JavaDoc i = torqueReports.iterator(); i.hasNext();)
477                 {
478                     Report torqueReport = (Report)i.next();
479                     try
480                     {
481                         reports.add( new ReportBridge(torqueReport) );
482                     }
483                     catch (org.xml.sax.SAXException JavaDoc e)
484                     {
485                         getLog().warn("Could not parse the report id=" +
486                                  torqueReport.getReportId() +
487                                  ", so it has been marked as deleted.");
488                         torqueReport.setDeleted(true);
489                         torqueReport.save();
490                     }
491                 }
492             }
493             else
494             {
495                 reports = Collections.EMPTY_LIST;
496             }
497
498             ScarabCache.put(reports, this, GET_SAVED_REPORTS, user);
499         }
500         else
501         {
502             reports = (List JavaDoc)obj;
503         }
504         return reports;
505     }
506
507
508     /**
509      * Gets a list of attributes for this module with a specific
510      * issue type.
511      */

512     public List JavaDoc getAttributes(IssueType issueType)
513         throws Exception JavaDoc
514     {
515         Criteria crit = new Criteria();
516         crit.add(RModuleAttributePeer.ISSUE_TYPE_ID, issueType.getIssueTypeId());
517         return getAttributes(crit);
518     }
519
520     /**
521      * gets a list of all of the Attributes in a Module based on the Criteria.
522      */

523     public List JavaDoc getAttributes(Criteria criteria)
524         throws Exception JavaDoc
525     {
526         List JavaDoc moduleAttributes = getRModuleAttributes(criteria);
527         List JavaDoc attributes = new ArrayList JavaDoc(moduleAttributes.size());
528         for (int i=0; i<moduleAttributes.size(); i++)
529         {
530             attributes.add(
531                ((RModuleAttribute) moduleAttributes.get(i)).getAttribute());
532         }
533         return attributes;
534     }
535
536     /**
537      * gets a list of all of the User Attributes in a Module.
538      */

539     public List JavaDoc getUserAttributes(IssueType issueType)
540         throws Exception JavaDoc
541     {
542         return getUserAttributes(issueType, true);
543     }
544
545     /**
546      * gets a list of all of the User Attributes in a Module.
547      */

548     public List JavaDoc getUserAttributes(IssueType issueType, boolean activeOnly)
549         throws Exception JavaDoc
550     {
551         List JavaDoc rModuleAttributes = getRModuleAttributes(issueType, activeOnly, USER);
552         List JavaDoc userAttributes = new ArrayList JavaDoc();
553
554         for (int i=0; i<rModuleAttributes.size(); i++)
555         {
556             Attribute att = ((RModuleAttribute)rModuleAttributes.get(i)).getAttribute();
557             userAttributes.add(att);
558         }
559         return userAttributes;
560     }
561
562
563     /**
564      * gets a list of permissions associated with the User Attributes
565      * that are active for this Module.
566      */

567     public List JavaDoc getUserPermissions(IssueType issueType)
568         throws Exception JavaDoc
569     {
570         List JavaDoc userAttrs = getUserAttributes(issueType, true);
571         List JavaDoc permissions = new ArrayList JavaDoc();
572         for (int i = 0; i < userAttrs.size(); i++)
573         {
574             String JavaDoc permission = ((Attribute)userAttrs.get(i)).getPermission();
575             if (!permissions.contains(permission))
576             {
577                 permissions.add(permission);
578             }
579         }
580         return permissions;
581     }
582
583     /**
584      * FIXME: can this be done more efficently?
585      * gets highest sequence number for module-attribute map
586      * so that a new RModuleAttribute can be added at the end.
587      */

588     public int getLastAttribute(IssueType issueType, String JavaDoc attributeType)
589         throws Exception JavaDoc
590     {
591         List JavaDoc moduleAttributes = getRModuleAttributes(issueType, false, attributeType);
592         int last = 0;
593
594         for (int i=0; i<moduleAttributes.size(); i++)
595         {
596                int order = ((RModuleAttribute) moduleAttributes.get(i))
597                          .getOrder();
598                if (order > last)
599                {
600                    last = order;
601                }
602         }
603         return last;
604     }
605
606
607     /**
608      * FIXME: can this be done more efficently?
609      * gets highest sequence number for module-attribute map
610      * so that a new RModuleAttribute can be added at the end.
611      */

612     public int getLastAttributeOption(Attribute attribute,
613                                       IssueType issueType)
614         throws Exception JavaDoc
615     {
616       List JavaDoc moduleOptions = getRModuleOptions(attribute, issueType);
617       int last = 0;
618       for (int i=0; i<moduleOptions.size(); i++)
619         {
620           int order = ((RModuleOption) moduleOptions.get(i))
621             .getOrder();
622           if (order > last)
623             {
624               last = order;
625             }
626         }
627       return last;
628     }
629
630   /*
631    * shift all the module options by 1 for all the non-active options with
632    * an order higher or equal than offset
633    */

634     public void shiftAttributeOption(Attribute attribute,
635                                     IssueType issueType,
636                                     int offset)
637         throws Exception JavaDoc
638     {
639       List JavaDoc moduleOptions = getRModuleOptions(attribute, issueType, false);
640       RModuleOption rmo;
641       for (int i=0; i<moduleOptions.size(); i++)
642         {
643           rmo = (RModuleOption) moduleOptions.get(i);
644           int order = rmo.getOrder();
645           if (order >= offset && !rmo.getActive())
646             {
647               rmo.setOrder(order+1);
648               rmo.save();
649             }
650         }
651     }
652
653     /**
654      * gets a list of all of the global Attributes that are not
655      * associated with this module and issue type
656      */

657     public List JavaDoc getAvailableAttributes(IssueType issueType,
658                                        String JavaDoc attributeType)
659         throws Exception JavaDoc
660     {
661         List JavaDoc allAttributes = AttributePeer.getAttributes(attributeType);
662         List JavaDoc availAttributes = new ArrayList JavaDoc();
663         List JavaDoc rModuleAttributes = getRModuleAttributes(issueType, false,
664                                                       attributeType);
665         List JavaDoc moduleAttributes = new ArrayList JavaDoc();
666         if (rModuleAttributes.isEmpty())
667         {
668              availAttributes = allAttributes;
669         }
670         else
671         {
672             for (int i=0; i<rModuleAttributes.size(); i++)
673             {
674                 moduleAttributes.add(
675                    ((RModuleAttribute) rModuleAttributes.get(i)).getAttribute());
676             }
677
678
679             for (int i=0; i<allAttributes.size(); i++)
680             {
681                 Attribute att = (Attribute)allAttributes.get(i);
682                 if (!moduleAttributes.contains(att))
683                 {
684                     availAttributes.add(att);
685                 }
686             }
687          }
688         return availAttributes;
689     }
690
691
692     /**
693      * gets a list of all of the Attribute options that are not
694      * associated with this module and attribute.
695      */

696     public List JavaDoc getAvailableAttributeOptions(Attribute attribute,
697                                              IssueType issueType)
698         throws Exception JavaDoc
699     {
700         List JavaDoc rModuleOptions = getRModuleOptions(attribute, issueType, false);
701         List JavaDoc moduleOptions = new ArrayList JavaDoc();
702         if (rModuleOptions != null)
703         {
704             for (int i=0; i<rModuleOptions.size(); i++)
705             {
706                 moduleOptions.add(
707                    ((RModuleOption) rModuleOptions.get(i)).getAttributeOption());
708             }
709         }
710
711         List JavaDoc allOptions = attribute.getAttributeOptions(true);
712         List JavaDoc availOptions = new ArrayList JavaDoc();
713
714         for (int i=0; i<allOptions.size(); i++)
715         {
716             AttributeOption option = (AttributeOption)allOptions.get(i);
717             if (!moduleOptions.contains(option) && !option.getDeleted())
718             {
719                 availOptions.add(option);
720             }
721         }
722         return availOptions;
723     }
724
725
726     /**
727      * Returns default issue list attributes for this module.
728      */

729     public List JavaDoc getDefaultRModuleUserAttributes(IssueType issueType)
730         throws Exception JavaDoc
731     {
732         List JavaDoc result = null;
733         Object JavaDoc obj = ScarabCache.get(this, GET_DEFAULT_RMODULE_USERATTRIBUTES,
734                                      issueType);
735         if (obj == null)
736         {
737             result = new LinkedList JavaDoc();
738             Attribute[] attributes = new Attribute[3];
739             int count = 0;
740             attributes[count++] = issueType.getDefaultTextAttribute(this);
741             if (attributes[0] == null)
742             {
743                 count = 0;
744             }
745             List JavaDoc rma1s = getRModuleAttributes(issueType, true, NON_USER);
746             Iterator JavaDoc i = rma1s.iterator();
747             while (i.hasNext())
748             {
749                 Attribute a = ((RModuleAttribute)i.next()).getAttribute();
750                 if (!a.isTextAttribute() || attributes[0] == null)
751                 {
752                     attributes[count++] = a;
753                     break;
754                 }
755             }
756
757             List JavaDoc rma2s = getRModuleAttributes(issueType, true, USER);
758             i = rma2s.iterator();
759             while (i.hasNext() && count < 3)
760             {
761                 Attribute a = ((RModuleAttribute)i.next()).getAttribute();
762                 attributes[count++] = a;
763             }
764
765             // if we still have less than 3 attributes, give the non user
766
// attributes another try
767
i = rma1s.iterator();
768             while (i.hasNext() && count < 3)
769             {
770                 Attribute a = ((RModuleAttribute)i.next()).getAttribute();
771                 if (!a.equals(attributes[0]) && !a.equals(attributes[1]))
772                 {
773                     attributes[count++] = a;
774                 }
775             }
776
777             for (int j=0; j<attributes.length; j++)
778             {
779                 if (attributes[j] != null)
780                 {
781                     RModuleUserAttribute rmua =
782                         RModuleUserAttributeManager.getInstance();
783                     rmua.setAttribute(attributes[j]);
784                     rmua.setIssueType(issueType);
785                     rmua.setOrder(j+1);
786                     result.add(rmua);
787                 }
788             }
789             ScarabCache.put(result, this, GET_DEFAULT_RMODULE_USERATTRIBUTES,
790                             issueType);
791         }
792         else
793         {
794             result = (List JavaDoc)obj;
795         }
796         return result;
797     }
798     /**
799      * This method is useful for getting an issue object
800      * by a String id. It has some logic in it for appending
801      * the Module Code as well as stripping spaces off the
802      * id value using the String.trim() method.
803      * @deprecated use IssueManager.getIssueById(String id, String defaultCode)
804      */

805     public Issue getIssueById(String JavaDoc id)
806         throws Exception JavaDoc
807     {
808         return IssueManager.getIssueById(id, getCode());
809     }
810
811     /**
812      * gets a list of the Issue Types for this module. only shows
813      * active issue types
814      */

815     public List JavaDoc getIssueTypes()
816         throws Exception JavaDoc
817     {
818         return getIssueTypes(true);
819     }
820
821     /**
822      * gets a list of the Issue Types for this module. only shows
823      * active issue types
824      */

825     public List JavaDoc getIssueTypes(boolean activeOnly)
826         throws Exception JavaDoc
827     {
828         List JavaDoc types = null;
829         Boolean JavaDoc activeOnlyValue = activeOnly ? Boolean.TRUE : Boolean.FALSE;
830         Object JavaDoc obj = ScarabCache.get(this, GET_ISSUE_TYPES, activeOnlyValue);
831         if (obj == null)
832         {
833             Criteria crit = new Criteria();
834             crit.addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
835                          IssueTypePeer. ISSUE_TYPE_ID);
836             crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId());
837             if (activeOnly)
838             {
839                 crit.add(RModuleIssueTypePeer.ACTIVE, true);
840             }
841             crit.add(IssueTypePeer.PARENT_ID, 0);
842             crit.add(IssueTypePeer.DELETED, 0);
843             crit.addAscendingOrderByColumn(RModuleIssueTypePeer.PREFERRED_ORDER);
844             types = IssueTypePeer.doSelect(crit);
845             ScarabCache.put(types, this, "getIssueTypes", activeOnlyValue);
846         }
847         else
848         {
849             types = (List JavaDoc)obj;
850         }
851         return types;
852     }
853
854     /**
855      * gets a list of the Issue Types for this module.
856      * that get listed in the left navigation. only shows active issue types.
857      */

858     public List JavaDoc getNavIssueTypes()
859         throws Exception JavaDoc
860     {
861         List JavaDoc types = null;
862         Object JavaDoc obj = getMethodResult().get(this, GET_NAV_ISSUE_TYPES);
863         if (obj == null)
864         {
865             Criteria crit = new Criteria();
866             crit.addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
867                          IssueTypePeer. ISSUE_TYPE_ID);
868             crit.add(RModuleIssueTypePeer. MODULE_ID, getModuleId());
869             crit.add(RModuleIssueTypePeer.ACTIVE, true);
870             crit.add(RModuleIssueTypePeer.DISPLAY, true);
871             crit.add(IssueTypePeer.PARENT_ID, 0);
872             crit.add(IssueTypePeer.DELETED, 0);
873             crit.addAscendingOrderByColumn(
874                 RModuleIssueTypePeer.PREFERRED_ORDER);
875             types = IssueTypePeer.doSelect(crit);
876             getMethodResult().put(types, this, GET_NAV_ISSUE_TYPES);
877         }
878         else
879         {
880             types = (List JavaDoc)obj;
881         }
882         return types;
883     }
884
885     /**
886      * gets a list of all of the issue types that are not associated with
887      * this module
888      */

889     public List JavaDoc getAvailableIssueTypes()
890         throws Exception JavaDoc
891     {
892         List JavaDoc availIssueTypes = null;
893         Object JavaDoc obj = ScarabCache.get(this, GET_AVAILABLE_ISSUE_TYPES);
894         if (obj == null)
895         {
896             availIssueTypes = new ArrayList JavaDoc();
897             List JavaDoc allIssueTypes = IssueTypePeer.getAllIssueTypes(false);
898             List JavaDoc currentIssueTypes = getIssueTypes(false);
899             Iterator JavaDoc iter = allIssueTypes.iterator();
900             while (iter.hasNext())
901             {
902                 IssueType issueType = (IssueType)iter.next();
903                 if (IssueTypePeer.getRootKey().equals(issueType.getParentId())
904                     && !IssueTypePeer.getRootKey().equals(issueType.getIssueTypeId())
905                     && !currentIssueTypes.contains(issueType))
906                 {
907                     availIssueTypes.add(issueType);
908                 }
909             }
910             ScarabCache.put(availIssueTypes, this, GET_AVAILABLE_ISSUE_TYPES);
911         }
912         else
913         {
914             availIssueTypes = (List JavaDoc)obj;
915         }
916         return availIssueTypes;
917     }
918
919     /**
920      * Returns RModuleAttributes associated with this module through the
921      * foreign key in the schema. This method will return an empty list, if the
922      * RModuleAttributes are inherited from its parent. Will not return an
923      * RModuleAttribute if the Attribute is deleted. NOTE: Do not try to add caching
924      * to this method as it seems to break things when an attribute is changed on
925      * an existing issue. (JSS)
926      */

927     public List JavaDoc getRModuleAttributes(Criteria crit)
928         throws TorqueException
929     {
930         crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
931         crit.addJoin(RModuleAttributePeer.ATTRIBUTE_ID,
932                      AttributePeer.ATTRIBUTE_ID);
933         crit.add(AttributePeer.DELETED, false);
934         return RModuleAttributePeer.doSelect(crit);
935     }
936
937     /**
938      * Overridden method.
939      */

940     public abstract List JavaDoc getRModuleOptions(Criteria crit)
941         throws TorqueException;
942
943
944     /**
945      * Adds module-attribute mapping to module.
946      */

947     public RModuleAttribute addRModuleAttribute(IssueType issueType,
948                                                 Attribute attribute)
949         throws Exception JavaDoc
950     {
951         String JavaDoc attributeType = null;
952         attributeType = (attribute.isUserAttribute() ? USER : NON_USER);
953
954         RModuleAttribute rma = new RModuleAttribute();
955         rma.setModuleId(getModuleId());
956         rma.setIssueTypeId(issueType.getIssueTypeId());
957         rma.setAttributeId(attribute.getAttributeId());
958         rma.setOrder(getLastAttribute(issueType, attributeType) + 1);
959         rma.setConditionsArray(attribute.getConditionsArray());
960         rma.save();
961         getRModuleAttributes(issueType, false, attributeType).add(rma);
962
963         // Add to template type
964
IssueType templateType = IssueTypeManager
965             .getInstance(issueType.getTemplateId(), false);
966         RModuleAttribute rma2 = new RModuleAttribute();
967         rma2.setModuleId(getModuleId());
968         rma2.setIssueTypeId(templateType.getIssueTypeId());
969         rma2.setAttributeId(attribute.getAttributeId());
970         rma2.setOrder(getLastAttribute(templateType, attributeType) + 1);
971         rma2.save();
972         return rma;
973     }
974
975     /**
976      * Adds module-attribute-option mapping to module.
977      */

978     public RModuleOption addRModuleOption(IssueType issueType,
979                                           AttributeOption option)
980         throws Exception JavaDoc
981     {
982         RModuleOption rmo = new RModuleOption();
983         rmo.setModuleId(getModuleId());
984         rmo.setIssueTypeId(issueType.getIssueTypeId());
985         rmo.setOptionId(option.getOptionId());
986         rmo.setDisplayValue(option.getName());
987         rmo.setOrder(getLastAttributeOption(option.getAttribute(), issueType) + 1);
988         return rmo;
989     }
990
991     public RModuleAttribute getRModuleAttribute(Attribute attribute,
992                             IssueType issueType)
993         throws Exception JavaDoc
994     {
995         RModuleAttribute rma = null;
996         List JavaDoc rmas = null;
997         if (attribute.isUserAttribute())
998         {
999             rmas = getRModuleAttributes(issueType, false, USER);
1000        }
1001        else
1002        {
1003            rmas = getRModuleAttributes(issueType, false, NON_USER);
1004        }
1005        Iterator JavaDoc i = rmas.iterator();
1006        while (i.hasNext())
1007        {
1008            rma = (RModuleAttribute)i.next();
1009            if (rma.getAttribute().equals(attribute))
1010            {
1011                break;
1012            }
1013            else
1014            {
1015                rma = null;
1016            }
1017        }
1018        return rma;
1019    }
1020
1021    /**
1022     * Overridden method. Calls the super method and if no results are
1023     * returned the call is passed on to the parent module.
1024     */

1025    public List JavaDoc getRModuleAttributes(IssueType issueType)
1026        throws Exception JavaDoc
1027    {
1028        return getRModuleAttributes(issueType, false);
1029    }
1030
1031    /**
1032     * Returns true if module has attributes associated with issue type.
1033     */

1034    public boolean hasAttributes(IssueType issueType)
1035        throws Exception JavaDoc
1036    {
1037        Criteria crit = new Criteria();
1038        crit.add(RModuleAttributePeer.ISSUE_TYPE_ID, issueType.getIssueTypeId());
1039        crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
1040        crit.addSelectColumn("count(" + RModuleAttributePeer.ATTRIBUTE_ID + ")");
1041        return ((Record)IssuePeer.doSelectVillageRecords(crit).get(0))
1042            .getValue(1).asInt() > 0;
1043    }
1044
1045    /**
1046     * Overridden method. Calls the super method and if no results are
1047     * returned the call is passed on to the parent module.
1048     */

1049    public List JavaDoc getRModuleAttributes(IssueType issueType, boolean activeOnly)
1050        throws Exception JavaDoc
1051    {
1052        return getRModuleAttributes(issueType, activeOnly, "all");
1053    }
1054
1055
1056    public List JavaDoc getRModuleAttributes(IssueType issueType, boolean activeOnly,
1057                                     String JavaDoc attributeType)
1058        throws Exception JavaDoc
1059    {
1060        List JavaDoc rmas = null;
1061        Boolean JavaDoc activeBool = (activeOnly ? Boolean.TRUE : Boolean.FALSE);
1062        Object JavaDoc obj = getMethodResult().get(this, GET_R_MODULE_ATTRIBUTES,
1063            issueType, activeBool, attributeType);
1064        if (obj == null)
1065        {
1066            Criteria crit = new Criteria();
1067            crit.add(RModuleAttributePeer.ISSUE_TYPE_ID,
1068                     issueType.getIssueTypeId());
1069            crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
1070            crit.addAscendingOrderByColumn(
1071                RModuleAttributePeer.PREFERRED_ORDER);
1072            crit.addAscendingOrderByColumn(
1073                RModuleAttributePeer.DISPLAY_VALUE);
1074            
1075            if (activeOnly)
1076            {
1077                crit.add(RModuleAttributePeer.ACTIVE, true);
1078            }
1079            
1080            crit.addJoin(AttributePeer.ATTRIBUTE_ID,
1081                     RModuleAttributePeer.ATTRIBUTE_ID);
1082            if (USER.equals(attributeType))
1083            {
1084                crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
1085                         AttributeTypePeer.USER_TYPE_KEY);
1086            }
1087            else if (NON_USER.equals(attributeType))
1088            {
1089                crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
1090                         AttributeTypePeer.USER_TYPE_KEY,
1091                         Criteria.NOT_EQUAL);
1092            }
1093            
1094            rmas = RModuleAttributePeer.doSelect(crit);
1095            getMethodResult().put(rmas, this, GET_R_MODULE_ATTRIBUTES,
1096                issueType, activeBool, attributeType);
1097        }
1098        else
1099        {
1100            rmas = (List JavaDoc)obj;
1101        }
1102        return rmas;
1103    }
1104
1105    /**
1106     * gets a list of all of the Attributes in this module.
1107     */

1108    public List JavaDoc getAllAttributes()
1109        throws Exception JavaDoc
1110    {
1111        return getAttributes(new Criteria());
1112    }
1113
1114    /**
1115     * gets a list of all of the active Attributes.
1116     * ordered by name
1117     */

1118    public List JavaDoc getActiveAttributesByName(IssueType issueType,
1119                                          String JavaDoc attributeType)
1120        throws Exception JavaDoc
1121    {
1122        Criteria crit = new Criteria();
1123        crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
1124        crit.add(RModuleAttributePeer.ISSUE_TYPE_ID,
1125                 issueType.getIssueTypeId());
1126        crit.addJoin(RModuleAttributePeer.ATTRIBUTE_ID,
1127                     AttributePeer.ATTRIBUTE_ID);
1128        crit.add(AttributePeer.DELETED, false);
1129        crit.add(RModuleAttributePeer.ACTIVE, true);
1130        if (USER.equals(attributeType))
1131        {
1132            crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
1133                     AttributeTypePeer.USER_TYPE_KEY);
1134            crit.addJoin(AttributePeer.ATTRIBUTE_ID,
1135                     RModuleAttributePeer.ATTRIBUTE_ID);
1136        }
1137        else if (NON_USER.equals(attributeType))
1138        {
1139            crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
1140                     AttributeTypePeer.USER_TYPE_KEY,
1141                     Criteria.NOT_EQUAL);
1142        }
1143        crit.addAscendingOrderByColumn(
1144                RModuleAttributePeer.DISPLAY_VALUE);
1145        return AttributePeer.doSelect(crit);
1146    }
1147
1148    public List JavaDoc getRModuleOptions(Attribute attribute, IssueType issueType)
1149        throws Exception JavaDoc
1150    {
1151        return getRModuleOptions(attribute, issueType, true);
1152    }
1153
1154    public List JavaDoc getRModuleOptions(Attribute attribute, IssueType issueType,
1155                                  boolean activeOnly)
1156        throws Exception JavaDoc
1157    {
1158        List JavaDoc allRModuleOptions = null;
1159        allRModuleOptions = getAllRModuleOptions(attribute, issueType);
1160
1161        if (allRModuleOptions != null)
1162        {
1163            if (activeOnly)
1164            {
1165                List JavaDoc activeRModuleOptions =
1166                    new ArrayList JavaDoc(allRModuleOptions.size());
1167                for (int i=0; i<allRModuleOptions.size(); i++)
1168                {
1169                    RModuleOption rmo =
1170                        (RModuleOption)allRModuleOptions.get(i);
1171                    if (rmo.getActive())
1172                    {
1173                        activeRModuleOptions.add(rmo);
1174                    }
1175                }
1176                allRModuleOptions = activeRModuleOptions;
1177            }
1178        }
1179        return allRModuleOptions;
1180    }
1181    
1182
1183    private List JavaDoc getAllRModuleOptions(Attribute attribute, IssueType issueType)
1184        throws Exception JavaDoc
1185    {
1186        if(attribute == null)
1187        {
1188          // during initilaization of a new query, no
1189
// attributes are available.
1190
// This check avoids a NLP
1191
return null;
1192        }
1193
1194        List JavaDoc rModOpts = null;
1195        Object JavaDoc obj = ScarabCache.get(this, GET_ALL_R_MODULE_OPTIONS,
1196                                     attribute, issueType);
1197        if (obj == null)
1198        {
1199            List JavaDoc options = attribute.getAttributeOptions(true);
1200            Integer JavaDoc[] optIds = null;
1201            if (options == null)
1202            {
1203                optIds = new Integer JavaDoc[0];
1204            }
1205            else
1206            {
1207                optIds = new Integer JavaDoc[options.size()];
1208            }
1209            for (int i=optIds.length-1; i>=0; i--)
1210            {
1211                optIds[i] = ((AttributeOption)options.get(i)).getOptionId();
1212            }
1213            
1214            if (optIds.length > 0)
1215            {
1216                Criteria crit = new Criteria();
1217                crit.add(RModuleOptionPeer.ISSUE_TYPE_ID, issueType.getIssueTypeId());
1218                crit.add(RModuleOptionPeer.MODULE_ID, getModuleId());
1219                crit.addIn(RModuleOptionPeer.OPTION_ID, optIds);
1220                crit.addAscendingOrderByColumn(RModuleOptionPeer.PREFERRED_ORDER);
1221                crit.addAscendingOrderByColumn(RModuleOptionPeer.DISPLAY_VALUE);
1222                rModOpts = getRModuleOptions(crit);
1223            }
1224            ScarabCache.put(rModOpts, this, GET_ALL_R_MODULE_OPTIONS,
1225                            attribute, issueType);
1226        }
1227        else
1228        {
1229            rModOpts = (List JavaDoc)obj;
1230        }
1231        return rModOpts;
1232    }
1233
1234    public RModuleOption getRModuleOption(AttributeOption option,
1235                                          IssueType issueType)
1236        throws Exception JavaDoc
1237    {
1238        RModuleOption rmo = null;
1239        List JavaDoc rmos = getRModuleOptions(option.getAttribute(),
1240                                      issueType, false);
1241        
1242        RModuleOption testRMO = null;
1243        for (Iterator JavaDoc i = rmos.iterator();i.hasNext();)
1244        {
1245            testRMO = (RModuleOption)i.next();
1246            if (testRMO.getAttributeOption().equals(option))
1247            {
1248                rmo = testRMO;
1249                break;
1250            }
1251        }
1252        return rmo;
1253    }
1254
1255    /**
1256     * Gets the modules list of attribute options. Uses the
1257     * RModuleOption table to do the join. returns null if there
1258     * is any error.
1259     */

1260    public List JavaDoc getAttributeOptions (Attribute attribute, IssueType issueType)
1261        throws Exception JavaDoc
1262    {
1263        List JavaDoc attributeOptions = null;
1264        try
1265        {
1266            List JavaDoc rModuleOptions = getOptionTree(attribute, issueType, false);
1267            attributeOptions = new ArrayList JavaDoc(rModuleOptions.size());
1268            for (int i=0; i<rModuleOptions.size(); i++)
1269            {
1270                attributeOptions.add(
1271                    ((RModuleOption)rModuleOptions.get(i)).getAttributeOption());
1272            }
1273        }
1274        catch (Exception JavaDoc e)
1275        {
1276        }
1277        return attributeOptions;
1278    }
1279
1280    public List JavaDoc getLeafRModuleOptions(Attribute attribute, IssueType issuetype)
1281        throws Exception JavaDoc
1282    {
1283        try
1284        {
1285            return getLeafRModuleOptions(attribute, issuetype, true);
1286        }
1287        catch (Exception JavaDoc e)
1288        {
1289            e.printStackTrace();
1290        }
1291        return null;
1292    }
1293
1294    public List JavaDoc getLeafRModuleOptions(Attribute attribute,
1295                                      IssueType issueType,
1296                                      boolean activeOnly)
1297        throws Exception JavaDoc
1298    {
1299        List JavaDoc rModOpts = null;
1300        Boolean JavaDoc activeBool = (activeOnly ? Boolean.TRUE : Boolean.FALSE);
1301        Object JavaDoc obj = getMethodResult().get(this, GET_LEAF_R_MODULE_OPTIONS,
1302                                           attribute, issueType, activeBool);
1303        if (obj == null)
1304        {
1305            rModOpts = getRModuleOptions(attribute, issueType, activeOnly);
1306            if (rModOpts != null)
1307            {
1308                
1309                // put options in a map for searching
1310
Map JavaDoc optionsMap = new HashMap JavaDoc((int)(rModOpts.size()*1.5));
1311                for (int i=rModOpts.size()-1; i>=0; i--)
1312                {
1313                    RModuleOption rmo = (RModuleOption)rModOpts.get(i);
1314                    optionsMap.put(rmo.getOptionId(), null);
1315                }
1316                
1317                // remove options with descendants in the list
1318
for (int i=rModOpts.size()-1; i>=0; i--)
1319                {
1320                    AttributeOption option =
1321                        ((RModuleOption)rModOpts.get(i)).getAttributeOption();
1322                    List JavaDoc descendants = option.getChildren();
1323                    if (descendants != null)
1324                    {
1325                        for (int j=descendants.size()-1; j>=0; j--)
1326                        {
1327                            AttributeOption descendant =
1328                                (AttributeOption)descendants.get(j);
1329                            if (optionsMap
1330                                 .containsKey(descendant.getOptionId()))
1331                            {
1332                                rModOpts.remove(i);
1333                                break;
1334                            }
1335                        }
1336                    }
1337                }
1338                getMethodResult().put(rModOpts, this, GET_LEAF_R_MODULE_OPTIONS,
1339                                      attribute, issueType, activeBool);
1340            }
1341        }
1342        else
1343        {
1344            rModOpts = (List JavaDoc)obj;
1345        }
1346        
1347        return rModOpts;
1348    }
1349
1350    /**
1351     * Gets a list of active RModuleOptions which have had their level
1352     * within the options for this module set.
1353     *
1354     * @param attribute an <code>Attribute</code> value
1355     * @return a <code>List</code> value
1356     * @exception TorqueException if an error occurs
1357     */

1358    public List JavaDoc getOptionTree(Attribute attribute, IssueType issueType)
1359        throws Exception JavaDoc
1360    {
1361        return getOptionTree(attribute, issueType, true);
1362    }
1363
1364    /**
1365     * Gets a list of RModuleOptions which have had their level
1366     * within the options for this module set.
1367     *
1368     * @param attribute an <code>Attribute</code> value
1369     * @param activeOnly a <code>boolean</code> value
1370     * @return a <code>List</code> value
1371     * @exception TorqueException if an error occurs
1372     */

1373    public List JavaDoc getOptionTree(Attribute attribute, IssueType issueType,
1374                              boolean activeOnly)
1375        throws Exception JavaDoc
1376    {
1377        // I think this code should place an option that had multiple parents -
1378
// OSX and Mac,BSD is usual example - into the list in multiple places
1379
// and it should have the level set differently for the two locations.
1380
// The code is currently only placing the option in the list once.
1381
// Since the behavior is not well spec'ed, leaving as it is. - jdm
1382

1383        List JavaDoc moduleOptions = null;
1384        moduleOptions = getRModuleOptions(attribute, issueType, activeOnly);
1385        if (moduleOptions == null)
1386        {
1387            return moduleOptions;
1388        }
1389
1390        int size = moduleOptions.size();
1391        List JavaDoc[] ancestors = new List JavaDoc[size];
1392
1393        // find all ancestors
1394
for (int i=size-1; i>=0; i--)
1395        {
1396            AttributeOption option =
1397                ((RModuleOption)moduleOptions.get(i)).getAttributeOption();
1398            ancestors[i] = option.getAncestors();
1399        }
1400
1401        for (int i=0; i<size; i++)
1402        {
1403            RModuleOption moduleOption = (RModuleOption)moduleOptions.get(i);
1404            int level = 1;
1405            if (ancestors[i] != null)
1406            {
1407                // Set level for first ancestor as the option is only
1408
// shown once.
1409
for (int j=ancestors[i].size()-1; j>=0; j--)
1410                {
1411                    AttributeOption ancestor =
1412                        (AttributeOption)ancestors[i].get(j);
1413
1414                    for (int k=0; k<i; k++)
1415                    {
1416                        RModuleOption potentialParent = (RModuleOption)
1417                            moduleOptions.get(k);
1418                        if (ancestor.getOptionId()
1419                            .equals(potentialParent.getOptionId()) &&
1420                            !ancestor.getOptionId()
1421                            .equals(moduleOption.getOptionId()) )
1422                        {
1423                            moduleOption.setLevel(level++);
1424                        }
1425                    }
1426                }
1427            }
1428        }
1429
1430        return moduleOptions;
1431    }
1432    
1433    /**
1434     * This method is implemented in ScarabModule
1435     */

1436    public abstract List JavaDoc getRModuleIssueTypes() throws TorqueException;
1437
1438    public List JavaDoc getRModuleIssueTypes(String JavaDoc sortColumn, String JavaDoc sortPolarity)
1439        throws TorqueException
1440    {
1441        List JavaDoc types = null;
1442        Object JavaDoc obj = ScarabCache.get(this, GET_R_MODULE_ISSUE_TYPES);
1443        if (obj == null)
1444        {
1445            Criteria crit = new Criteria();
1446            crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId())
1447                .addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
1448                         IssueTypePeer.ISSUE_TYPE_ID)
1449                .add(IssueTypePeer.PARENT_ID, 0)
1450                .add(IssueTypePeer.DELETED, 0);
1451            if (sortColumn.equals("name"))
1452            {
1453                if (sortPolarity.equals("desc"))
1454                {
1455                    crit.addDescendingOrderByColumn(IssueTypePeer.NAME);
1456                }
1457                else
1458                {
1459                    crit.addAscendingOrderByColumn(IssueTypePeer.NAME);
1460                }
1461            }
1462            else
1463            {
1464                // sortColumn defaults to sequence #
1465
if (sortPolarity.equals("desc"))
1466                {
1467                    crit.addDescendingOrderByColumn(RModuleIssueTypePeer
1468                                                    .PREFERRED_ORDER);
1469                }
1470                else
1471                {
1472                    crit.addAscendingOrderByColumn(RModuleIssueTypePeer
1473                                                   .PREFERRED_ORDER);
1474                }
1475            }
1476            types = RModuleIssueTypePeer.doSelect(crit);
1477            ScarabCache.put(types, this, GET_R_MODULE_ISSUE_TYPES);
1478        }
1479        else
1480        {
1481            types = (List JavaDoc) obj;
1482        }
1483        return types;
1484    }
1485
1486    /**
1487     * Adds attribute options to a module.
1488     */

1489    public void addAttributeOption(IssueType issueType, AttributeOption option)
1490        throws Exception JavaDoc
1491    {
1492        RModuleOption rmo = addRModuleOption(issueType, option);
1493        rmo.save();
1494        shiftAttributeOption(option.getAttribute(), issueType, rmo.getOrder());
1495
1496        // add module-attributeoption mappings to template type
1497
IssueType templateType = IssueTypeManager
1498                 .getInstance(issueType.getTemplateId());
1499        RModuleOption rmo2 = addRModuleOption(templateType, option);
1500        rmo2.save();
1501        //FIXME: is it useful to shift options for the templateType?
1502
//shiftAttributeOption(option.getAttribute(), templateType, rmo.getOrder());
1503

1504        //if the cache is not cleared, when two options are added at the same time,
1505
//getLastAttributeOption does not take into account the newest active options.
1506
ScarabCache.clear();
1507    }
1508  
1509
1510    public void setRmaBasedOnIssueType(RIssueTypeAttribute ria)
1511        throws Exception JavaDoc
1512    {
1513        RModuleAttribute rma = new RModuleAttribute();
1514        rma.setModuleId(getModuleId());
1515        rma.setIssueTypeId(ria.getIssueTypeId());
1516        rma.setAttributeId(ria.getAttributeId());
1517        rma.setActive(ria.getActive());
1518        rma.setRequired(ria.getRequired());
1519        rma.setOrder(ria.getOrder());
1520        rma.setQuickSearch(ria.getQuickSearch());
1521        rma.setDefaultTextFlag(ria.getDefaultTextFlag());
1522        rma.save();
1523        RModuleAttribute rma2 = rma.copy();
1524        rma2.setModuleId(getModuleId());
1525        rma2.setIssueTypeId(ria.getIssueType().getTemplateId());
1526        rma2.setAttributeId(ria.getAttributeId());
1527        rma2.setActive(ria.getActive());
1528        rma2.setRequired(ria.getRequired());
1529        rma2.setOrder(ria.getOrder());
1530        rma2.setQuickSearch(ria.getQuickSearch());
1531        rma2.setDefaultTextFlag(ria.getDefaultTextFlag());
1532        rma2.save();
1533    }
1534
1535    public void setRmoBasedOnIssueType(RIssueTypeOption rio)
1536        throws Exception JavaDoc
1537    {
1538        RModuleOption rmo = new RModuleOption();
1539        rmo.setModuleId(getModuleId());
1540        rmo.setIssueTypeId(rio.getIssueTypeId());
1541        rmo.setOptionId(rio.getOptionId());
1542        rmo.setActive(rio.getActive());
1543        rmo.setOrder(rio.getOrder());
1544        rmo.setWeight(rio.getWeight());
1545        rmo.save();
1546        RModuleOption rmo2 = rmo.copy();
1547        rmo2.setModuleId(getModuleId());
1548        rmo2.setIssueTypeId(rio.getIssueType().getTemplateId());
1549        rmo2.setOptionId(rio.getOptionId());
1550        rmo2.setActive(rio.getActive());
1551        rmo2.setOrder(rio.getOrder());
1552        rmo2.setWeight(rio.getWeight());
1553        rmo2.save();
1554    }
1555
1556    protected String JavaDoc getValidationMessage(String JavaDoc typeName, String JavaDoc detail)
1557    {
1558        // TODO: i18n
1559
return "The issue type, " + typeName + ", failed its integrity check and "
1560            + "has not been added to module, " + getName() + ". Error message was '" +
1561            detail + "'.";
1562    }
1563
1564    public boolean includesIssueType(IssueType issueType)
1565        throws Exception JavaDoc
1566    {
1567        Criteria crit = new Criteria();
1568        crit.add(RModuleIssueTypePeer.MODULE_ID,
1569                 getModuleId());
1570        crit.add(RModuleIssueTypePeer.ISSUE_TYPE_ID,
1571                 issueType.getIssueTypeId());
1572        return RModuleIssueTypePeer.count(crit) > 0;
1573    }
1574
1575    /**
1576     * Adds an issue type to a module
1577     * Copies properties from the global issue type's settings
1578     */

1579    public void addIssueType(IssueType issueType)
1580        throws Exception JavaDoc, ValidationException
1581    {
1582        // do some validation, refuse to add an issue type that is in a bad
1583
// state
1584
if (issueType == null)
1585        {
1586            throw new ValidationException(L10NKeySet.ExceptionIntegrityCheckFailure,
1587                    "NULL",
1588                    getName(),
1589                    "Issue type was null");
1590        }
1591
1592        // check that the issueType is not already added.
1593
if (includesIssueType(issueType))
1594        {
1595            throw new ValidationException(L10NKeySet.ExceptionDuplicateIssueType,
1596                    issueType,
1597                    getName());
1598        }
1599
1600        String JavaDoc typeName = issueType.getName();
1601        // check attribute groups
1602
List JavaDoc testGroups = issueType.getAttributeGroups(null, false);
1603        try
1604        {
1605            if (testGroups == null)
1606            {
1607                Localizable l10nMessage = new L10NMessage(L10NKeySet.IssueTypeWasNull);
1608                throw new ValidationException(L10NKeySet.ExceptionIntegrityCheckFailure,
1609                        typeName,
1610                        getName(),
1611                        l10nMessage);
1612            }
1613            else
1614            {
1615                for (Iterator JavaDoc i = testGroups.iterator(); i.hasNext();)
1616                {
1617                    AttributeGroup group = (AttributeGroup)i.next();
1618                    // check attributes
1619
List JavaDoc attrs = group.getAttributes();
1620                    if (attrs != null)
1621                    {
1622                        for (Iterator JavaDoc j = attrs.iterator(); j.hasNext();)
1623                        {
1624                            // check attribute-attribute group maps
1625
Attribute attr = (Attribute)j.next();
1626                            if (attr == null)
1627                            {
1628                                L10NMessage l10nMessage = new L10NMessage(L10NKeySet.AttributesContainsNull);
1629                                throw new ValidationException(L10NKeySet.ExceptionIntegrityCheckFailure,
1630                                        typeName,
1631                                        getName(),
1632                                        l10nMessage);
1633                            }
1634                            
1635                            // TODO: add workflow validation
1636

1637                            RAttributeAttributeGroup raag = group.getRAttributeAttributeGroup(attr);
1638                            if (raag == null)
1639                            {
1640                                L10NMessage l10nMessage = new L10NMessage(L10NKeySet.AttributeMappingIsMissing, attr.getName());
1641                                throw new ValidationException(L10NKeySet.ExceptionIntegrityCheckFailure,
1642                                        typeName,
1643                                        getName(),
1644                                        l10nMessage);
1645                          
1646                            }
1647
1648                            // check attribute-issue type maps
1649
RIssueTypeAttribute ria = issueType.getRIssueTypeAttribute(attr);
1650                            if (ria == null)
1651                            {
1652                                L10NMessage l10nMessage = new L10NMessage(L10NKeySet.AttributeToIssueTypeMappingIsMissing, attr.getName());
1653                                throw new ValidationException(L10NKeySet.ExceptionIntegrityCheckFailure,
1654                                        typeName,
1655                                        getName(),
1656                                        l10nMessage);
1657                            }
1658
1659                            // check options
1660
List JavaDoc rios = issueType.getRIssueTypeOptions(attr, false);
1661                            if (rios != null)
1662                            {
1663                                for (Iterator JavaDoc k=rios.iterator(); k.hasNext();)
1664                                {
1665                                    if (k.next() == null)
1666                                    {
1667                                        L10NMessage l10nMessage = new L10NMessage(L10NKeySet.ListOfOptionsMissing, attr.getName());
1668                                                throw new ValidationException(L10NKeySet.ExceptionIntegrityCheckFailure,
1669                                                typeName,
1670                                                getName(),
1671                                                l10nMessage);
1672                                    }
1673                                }
1674                            }
1675                        }
1676                    }
1677                }
1678            }
1679        }
1680        catch (ValidationException ve)
1681        {
1682            throw ve;
1683        }
1684        catch (Exception JavaDoc e)
1685        {
1686            throw new ValidationException(
1687                    L10NKeySet.ExceptionGeneral,
1688                    e.getMessage(),
1689                    e);
1690        }
1691
1692        // okay we passed, start modifying tables
1693

1694        // add module-issue type mapping
1695
RModuleIssueType rmit = new RModuleIssueType();
1696        rmit.setModuleId(getModuleId());
1697        rmit.setIssueTypeId(issueType.getIssueTypeId());
1698        rmit.setActive(true);
1699        rmit.setDisplay(false);
1700        rmit.setOrder(getRModuleIssueTypes().size() + 1);
1701        rmit.setDedupe(issueType.getDedupe());
1702        rmit.save();
1703
1704        // add user attributes
1705
List JavaDoc userRIAs = issueType.getRIssueTypeAttributes(false, "user");
1706        for (int m=0; m<userRIAs.size(); m++)
1707        {
1708            RIssueTypeAttribute userRia = (RIssueTypeAttribute)userRIAs.get(m);
1709            setRmaBasedOnIssueType(userRia);
1710        }
1711
1712        // add workflow
1713
WorkflowFactory.getInstance().addIssueTypeWorkflowToModule(this, issueType);
1714
1715        // add attribute groups
1716
List JavaDoc groups = issueType.getAttributeGroups(null, false);
1717        if (groups.isEmpty())
1718        {
1719            // Create default groups
1720
AttributeGroup ag = createNewGroup(issueType);
1721            ag.setOrder(1);
1722            ag.setDedupe(true);
1723            ag.setDescription(null);
1724            ag.save();
1725            AttributeGroup ag2 = createNewGroup(issueType);
1726            ag2.setOrder(3);
1727            ag2.setDedupe(false);
1728            ag2.setDescription(null);
1729            ag2.save();
1730        }
1731        else
1732        {
1733            // Inherit attribute groups from issue type
1734
for (int i=0; i<groups.size(); i++)
1735            {
1736                AttributeGroup group = (AttributeGroup)groups.get(i);
1737                AttributeGroup moduleGroup = group.copyGroup();
1738                moduleGroup.setModuleId(getModuleId());
1739                moduleGroup.setIssueTypeId(issueType.getIssueTypeId());
1740                moduleGroup.save();
1741
1742                // add attributes
1743
List JavaDoc attrs = group.getAttributes();
1744                if (attrs != null)
1745                {
1746                    for (int j=0; j<attrs.size(); j++)
1747                    {
1748                        // save attribute-attribute group maps
1749
Attribute attr = (Attribute)attrs.get(j);
1750                        RAttributeAttributeGroup raag = group.getRAttributeAttributeGroup(attr);
1751                        RAttributeAttributeGroup moduleRaag = new RAttributeAttributeGroup();
1752                        moduleRaag.setAttributeId(raag.getAttributeId());
1753                        moduleRaag.setOrder(raag.getOrder());
1754                        moduleRaag.setGroupId(moduleGroup.getAttributeGroupId());
1755                        moduleRaag.save();
1756
1757                        // save attribute-module maps
1758
RIssueTypeAttribute ria = issueType.getRIssueTypeAttribute(attr);
1759                        setRmaBasedOnIssueType(ria);
1760
1761                        // save options
1762
List JavaDoc rios = issueType.getRIssueTypeOptions(attr, false);
1763                        if (rios != null)
1764                        {
1765                            for (int k=0; k<rios.size(); k++)
1766                            {
1767                                RIssueTypeOption rio = (RIssueTypeOption)rios.get(k);
1768                                setRmoBasedOnIssueType(rio);
1769                            }
1770                        }
1771                    }
1772                }
1773            }
1774        }
1775    }
1776
1777    public RModuleIssueType getRModuleIssueType(IssueType issueType)
1778        throws Exception JavaDoc
1779    {
1780        RModuleIssueType rmit = null;
1781        try
1782        {
1783            SimpleKey[] keys = { SimpleKey.keyFor(getModuleId()),
1784                                 SimpleKey.keyFor(issueType.getIssueTypeId())
1785            };
1786            rmit = RModuleIssueTypeManager.getInstance(new ComboKey(keys));
1787        }
1788        catch (NoRowsException e)
1789        {
1790            // ignore and return null, if the rmit does not exist
1791
}
1792        return rmit;
1793    }
1794
1795
1796    public List JavaDoc getTemplateTypes()
1797        throws Exception JavaDoc
1798    {
1799        List JavaDoc templateTypes = new ArrayList JavaDoc();
1800        Object JavaDoc obj = ScarabCache.get(this, GET_TEMPLATE_TYPES);
1801        if (obj == null)
1802        {
1803            Criteria crit = new Criteria();
1804            crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId())
1805                .addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
1806                     IssueTypePeer.ISSUE_TYPE_ID)
1807                .add(IssueTypePeer.DELETED, 0);
1808            List JavaDoc rmits = RModuleIssueTypePeer.doSelect(crit);
1809            for (int i=0; i<rmits.size(); i++)
1810            {
1811                RModuleIssueType rmit = (RModuleIssueType)rmits.get(i);
1812                IssueType templateType = rmit.getIssueType().getTemplateIssueType();
1813                templateTypes.add(templateType);
1814            }
1815            ScarabCache.put(templateTypes, this, GET_TEMPLATE_TYPES);
1816        }
1817        else
1818        {
1819            templateTypes = (List JavaDoc)obj;
1820        }
1821        return templateTypes;
1822    }
1823
1824    /**
1825     * Determines whether this module allows users to vote many times for
1826     * the same issue. This feature needs schema change to allow a
1827     * configuration screen. Currently only one vote per issue is supported
1828     *
1829     * @return false
1830     */

1831    public boolean allowsMultipleVoting()
1832    {
1833        return false;
1834    }
1835
1836    /**
1837     * How many votes does the user have left to cast. Currently always
1838     * returns 1, so a user has unlimited voting rights. Should look to
1839     * UserVote for the answer when implemented properly.
1840     */

1841    public int getUnusedVoteCount(ScarabUser user)
1842    {
1843        return 1;
1844    }
1845
1846    /**
1847     * Returns list of queries needing approval.
1848     */

1849    public List JavaDoc getUnapprovedQueries() throws Exception JavaDoc
1850    {
1851        List JavaDoc queries = null;
1852        Object JavaDoc obj = ScarabCache.get(this, GET_UNAPPROVED_QUERIES);
1853        if (obj == null)
1854        {
1855            Criteria crit = new Criteria(3);
1856            crit.add(QueryPeer.APPROVED, 0)
1857                .add(QueryPeer.DELETED, 0)
1858                .add(QueryPeer.MODULE_ID, getModuleId());
1859            queries = QueryPeer.doSelect(crit);
1860            ScarabCache.put(queries, this, GET_UNAPPROVED_QUERIES);
1861        }
1862        else
1863        {
1864            queries = (List JavaDoc)obj;
1865        }
1866        return queries;
1867    }
1868
1869    /**
1870     * Returns list of enter issue templates needing approval.
1871     */

1872    public List JavaDoc getUnapprovedTemplates() throws Exception JavaDoc
1873    {
1874        List JavaDoc templates = null;
1875        Object JavaDoc obj = ScarabCache.get(this, GET_UNAPPROVED_TEMPLATES);
1876        if (obj == null)
1877        {
1878            Criteria crit = new Criteria(3);
1879            crit.add(IssueTemplateInfoPeer.APPROVED, 0)
1880                .addJoin(IssuePeer.ISSUE_ID, IssueTemplateInfoPeer.ISSUE_ID)
1881                .add(IssuePeer.DELETED, 0)
1882                .add(IssuePeer.MODULE_ID, getModuleId());
1883            templates = IssuePeer.doSelect(crit);
1884            ScarabCache.put(templates, this, GET_UNAPPROVED_TEMPLATES);
1885        }
1886        else
1887        {
1888            templates = (List JavaDoc)obj;
1889        }
1890        return templates;
1891    }
1892
1893    /**
1894     * for a new module: inherit issue types from parent module and
1895     * from the issue types marked as default
1896     * parent configuration takes precedence over default
1897     */

1898    protected void setInitialAttributesAndIssueTypes()
1899        throws Exception JavaDoc
1900    {
1901        isInitializing = true;
1902        ValidationException ve = null;
1903        try
1904        {
1905        // Add defaults for issue types and attributes
1906
// from parent module
1907
Module parentModule = ModuleManager.getInstance(getParentId());
1908        inheritFromParent(parentModule);
1909
1910        List JavaDoc defaultIssueTypes = IssueTypePeer.getDefaultIssueTypes();
1911        for (int i=0; i< defaultIssueTypes.size(); i++)
1912        {
1913            IssueType defaultIssueType = (IssueType)defaultIssueTypes.get(i);
1914            if (!includesIssueType(defaultIssueType))
1915            {
1916                try
1917                {
1918                    addIssueType(defaultIssueType);
1919                }
1920                catch (ValidationException e)
1921                {
1922                    // if one issue type is bad, continue with the rest, if
1923
// more than one bad issue type is found, stop.
1924
if (ve == null)
1925                    {
1926                        ve = e;
1927                    }
1928                    else
1929                    {
1930                        ve = new ValidationException(
1931                                L10NKeySet.ExceptionMultipleProblems,
1932                                ve.getMessage(),
1933                                e);//WORK: what about the stack trace ?
1934
isInitializing = false;
1935                        throw ve;
1936                    }
1937                }
1938            }
1939        }
1940        }
1941        finally
1942        {
1943            isInitializing = false;
1944        }
1945        if (ve != null)
1946        {
1947            throw ve;
1948        }
1949    }
1950    
1951    /**
1952     * sets up attributes and issue types for this module based on.
1953     * the parent module
1954     */

1955    protected void inheritFromParent(Module parentModule)
1956        throws Exception JavaDoc
1957    {
1958        Integer JavaDoc newModuleId = getModuleId();
1959        AttributeGroup ag1;
1960        AttributeGroup ag2;
1961        RModuleAttribute rma1 = null;
1962        RModuleAttribute rma2 = null;
1963            
1964        //save RModuleAttributes for template types.
1965
List JavaDoc templateTypes = parentModule.getTemplateTypes();
1966        for (int i=0; i<templateTypes.size(); i++)
1967        {
1968            IssueType it = (IssueType)templateTypes.get(i);
1969            List JavaDoc rmas = parentModule.getRModuleAttributes(it);
1970            for (int j=0; j<rmas.size(); j++)
1971            {
1972                rma1 = (RModuleAttribute)rmas.get(j);
1973                rma2 = rma1.copy();
1974                rma2.setModuleId(newModuleId);
1975                rma2.setAttributeId(rma1.getAttributeId());
1976                rma2.setIssueTypeId(rma1.getIssueTypeId());
1977                getLog().debug("[ASM] Saving rma for new template type: " +
1978                                    rma2.getModuleId()
1979                                    + "-" + rma2.getIssueTypeId() + "-" +
1980                                    rma2.getAttributeId());
1981                rma2.save();
1982            }
1983        }
1984
1985        // set module-issue type mappings
1986
List JavaDoc rmits = parentModule.getRModuleIssueTypes();
1987        for (int i=0; i<rmits.size(); i++)
1988        {
1989            RModuleIssueType rmit1 = (RModuleIssueType)rmits.get(i);
1990            RModuleIssueType rmit2 = rmit1.copy();
1991            rmit2.setModuleId(newModuleId);
1992            rmit2.save();
1993            IssueType issueType = rmit1.getIssueType();
1994
1995            // set attribute group defaults
1996
List JavaDoc attributeGroups = issueType
1997                .getAttributeGroups(parentModule, true);
1998            for (int j=0; j<attributeGroups.size(); j++)
1999            {
2000                ag1 = (AttributeGroup)attributeGroups.get(j);
2001                ag2 = ag1.copy();
2002                ag2.setModuleId(newModuleId);
2003                ag2.getRAttributeAttributeGroups().clear(); // are saved later
2004
ag2.save();
2005
2006                List JavaDoc attributes = ag1.getAttributes();
2007                for (int k=0; k<attributes.size(); k++)
2008                {
2009                    Attribute attribute = (Attribute)attributes.get(k);
2010
2011                    // set attribute-attribute group defaults
2012
RAttributeAttributeGroup raag1 = ag1
2013                        .getRAttributeAttributeGroup(attribute);
2014                    RAttributeAttributeGroup raag2 = raag1.copy();
2015                    raag2.setGroupId(ag2.getAttributeGroupId());
2016                    raag2.setAttributeId(raag1.getAttributeId());
2017                    raag2.setOrder(raag1.getOrder());
2018                    raag2.save();
2019                }
2020            }
2021
2022            // set module-attribute defaults
2023
List JavaDoc rmas = parentModule.getRModuleAttributes(issueType);
2024            if (rmas != null && rmas.size() >0)
2025            {
2026                for (int j=0; j<rmas.size(); j++)
2027                {
2028                    rma1 = (RModuleAttribute)rmas.get(j);
2029                    rma2 = rma1.copy();
2030                    rma2.setModuleId(newModuleId);
2031                    rma2.setAttributeId(rma1.getAttributeId());
2032                    rma2.setIssueTypeId(rma1.getIssueTypeId());
2033                    rma2.save();
2034
2035                    // set module-option mappings
2036
Attribute attribute = rma1.getAttribute();
2037                    if (attribute.isOptionAttribute())
2038                    {
2039                        List JavaDoc rmos = parentModule.getRModuleOptions(attribute,
2040                                                                   issueType);
2041                        if (rmos != null && rmos.size() > 0)
2042                        {
2043                            for (int m=0; m<rmos.size(); m++)
2044                            {
2045                                RModuleOption rmo1 = (RModuleOption)rmos.get(m);
2046                                RModuleOption rmo2 = rmo1.copy();
2047                                rmo2.setOptionId(rmo1.getOptionId());
2048                                rmo2.setModuleId(newModuleId);
2049                                rmo2.setIssueTypeId(issueType.getIssueTypeId());
2050                                rmo2.save();
2051
2052                                // Save module-option mappings for template types
2053
RModuleOption rmo3 = rmo1.copy();
2054                                rmo3.setOptionId(rmo1.getOptionId());
2055                                rmo3.setModuleId(newModuleId);
2056                                rmo3.setIssueTypeId(issueType.getTemplateId());
2057                                rmo3.save();
2058                            }
2059                        }
2060                    }
2061                }
2062            }
2063        }
2064    }
2065
2066    /**
2067     * Determines whether this module is accepting new issues. This default
2068     * implementation allows new issues if the module has not been deleted.
2069     */

2070    public boolean allowsNewIssues()
2071    {
2072        return !getDeleted();
2073    }
2074
2075    /**
2076     * Determines whether this module accepts issues. This default
2077     * implementation does allow issues.
2078     */

2079    public boolean allowsIssues()
2080    {
2081        return true;
2082    }
2083
2084    /**
2085     * Returns true if no issue types are associated with this module, or if the module
2086     * is currently getting its initial values set.
2087     */

2088    public boolean isInitializing()
2089        throws Exception JavaDoc
2090    {
2091        return isInitializing;
2092    }
2093
2094
2095    /**
2096     * @see org.tigris.scarab.om.Module#isGlobalModule()
2097     */

2098    public boolean isGlobalModule()
2099    {
2100        return Module.ROOT_ID.equals(getModuleId());
2101    }
2102
2103    // FIXME! should localize
2104
private static final String JavaDoc REGEX_PREFIX =
2105        "([:alpha:]+\\d+)|(issue|bug|artifact";
2106    private static final String JavaDoc REGEX_SUFFIX =
2107        ")\\s*#?([:alpha:]*\\d+)";
2108
2109    public String JavaDoc getIssueRegexString()
2110        throws TorqueException
2111    {
2112        // regex = /(issue|bug)\s+#?\d+/i
2113
List JavaDoc rmitsList = getRModuleIssueTypes();
2114        StringBuffer JavaDoc regex = new StringBuffer JavaDoc(30 + 10 * rmitsList.size());
2115        regex.append(REGEX_PREFIX);
2116        Iterator JavaDoc rmits = rmitsList.iterator();
2117        while (rmits.hasNext())
2118        {
2119            regex.append('|')
2120                .append(((RModuleIssueType)rmits.next()).getDisplayName());
2121        }
2122        regex.append(REGEX_SUFFIX);
2123        return regex.toString();
2124    }
2125
2126    /**
2127     * @see org.tigris.scarab.om.Module#getIssueRegex()
2128     */

2129    public REProgram getIssueRegex()
2130        throws TorqueException
2131    {
2132        String JavaDoc regex = getIssueRegexString();
2133        RECompiler rec = new RECompiler();
2134        REProgram rep = null;
2135        try
2136        {
2137            rep = rec.compile(regex);
2138        }
2139        catch (RESyntaxException e)
2140        {
2141            getLog().error("Could not compile regex: " + regex, e);
2142            try
2143            {
2144                rep = rec.compile(REGEX_PREFIX + REGEX_SUFFIX);
2145            }
2146            catch (RESyntaxException ee)
2147            {
2148                // this should not happen, but it might when we localize
2149
getLog().error("Could not compile standard regex", ee);
2150                try
2151                {
2152                    rep = rec.compile("[:alpha:]+\\d+");
2153                }
2154                catch (RESyntaxException eee)
2155                {
2156                    // this will never happen, but log it, just in case
2157
getLog().error("Could not compile simple id regex", eee);
2158                }
2159            }
2160        }
2161        // FIXME: we should cache the above result
2162
return rep;
2163    }
2164
2165    /**
2166     * All emails related to this module will have a copy sent to
2167     * this address. A system-wide default email address can be specified in
2168     * Scarab.properties with the key: scarab.email.archive.toAddress
2169     */

2170    public abstract String JavaDoc getArchiveEmail();
2171
2172    /**
2173     * Simple implementation returns the single configured default locale
2174     * from TR.props. Will be replaced by a way to set this per module.
2175     *
2176     * @return a Locale selected for the Fulcrum Localization context
2177     */

2178    public Locale JavaDoc getLocale()
2179    {
2180        return ScarabConstants.DEFAULT_LOCALE;
2181    }
2182
2183    /**
2184     * The default address that is used to fill out either the From or
2185     * ReplyTo header on emails related to this module. In many cases
2186     * the From field is taken as the user who acted that resulted in the
2187     * email, but replies should still go to the central location for
2188     * the module, so in this address would be used in the ReplyTo field.
2189     *
2190     * @return a <code>String[]</code> of length=2 where the first element
2191     * is a name such as "Scarab System" and the second is an email address.
2192     */

2193    public String JavaDoc[] getSystemEmail()
2194    {
2195        String JavaDoc name = Turbine.getConfiguration()
2196            .getString("scarab.email.default.fromName");
2197        if (name == null || name.length() == 0)
2198        {
2199            name = Localization.format(ScarabConstants.DEFAULT_BUNDLE_NAME,
2200                getLocale(),
2201                "DefaultEmailNameForModule",
2202                getRealName().toUpperCase());
2203        }
2204        
2205        String JavaDoc email = Turbine.getConfiguration()
2206            .getString("scarab.email.default.fromAddress");
2207
2208        if (email == null || email.length() == 0)
2209        {
2210            email = getArchiveEmail();
2211        }
2212        if (email == null || email.length() == 0)
2213        {
2214            email = "help@localhost";
2215        }
2216        String JavaDoc[] result = {name, email};
2217        return result;
2218    }
2219
2220    /**
2221     * Used for ordering Groups.
2222     *
2223     * @param obj The Object to compare to.
2224     * @return -1 if the name of the other object is lexically greater than
2225     * this group, 1 if it is lexically lesser, 0 if they are equal.
2226     */

2227    public int compareTo(Object JavaDoc obj)
2228    {
2229        //TODO [HD] what about using instanceof, or
2230
// probably better delete the whole
2231
// if-block (see note n ScarabModule.compereTo()
2232
if (this.getClass() != obj.getClass())
2233        {
2234            throw new ClassCastException JavaDoc(); //EXCEPTION
2235
}
2236        String JavaDoc name1 = ((Group)obj).getName();
2237        String JavaDoc name2 = this.getName();
2238
2239        return name2.compareTo(name1);
2240    }
2241
2242    public String JavaDoc toString()
2243    {
2244        String JavaDoc name = getName();
2245        if (name == null)
2246        {
2247            name = getRealName();
2248        }
2249        if (name == null)
2250        {
2251            name = getClass().getName();
2252        }
2253        return name;
2254    }
2255
2256    private MethodResultCache getMethodResult()
2257    {
2258        return ModuleManager.getMethodResult();
2259    }
2260
2261}
2262
2263
Popular Tags