Source Code Cross Referenced for AbstractScarabModule.java in  » Issue-Tracking » scarab-0.21 » org » tigris » scarab » om » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Issue Tracking » scarab 0.21 » org.tigris.scarab.om 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package org.tigris.scarab.om;
0002:
0003:        /* ================================================================
0004:         * Copyright (c) 2000-2005 CollabNet.  All rights reserved.
0005:         * 
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions are
0008:         * met:
0009:         * 
0010:         * 1. Redistributions of source code must retain the above copyright
0011:         * notice, this list of conditions and the following disclaimer.
0012:         * 
0013:         * 2. Redistributions in binary form must reproduce the above copyright
0014:         * notice, this list of conditions and the following disclaimer in the
0015:         * documentation and/or other materials provided with the distribution.
0016:         * 
0017:         * 3. The end-user documentation included with the redistribution, if
0018:         * any, must include the following acknowlegement: "This product includes
0019:         * software developed by Collab.Net <http://www.Collab.Net/>."
0020:         * Alternately, this acknowlegement may appear in the software itself, if
0021:         * and wherever such third-party acknowlegements normally appear.
0022:         * 
0023:         * 4. The hosted project names must not be used to endorse or promote
0024:         * products derived from this software without prior written
0025:         * permission. For written permission, please contact info@collab.net.
0026:         * 
0027:         * 5. Products derived from this software may not use the "Tigris" or 
0028:         * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without 
0029:         * prior written permission of Collab.Net.
0030:         * 
0031:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0032:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0033:         * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0034:         * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
0035:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0036:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
0037:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0038:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
0039:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
0040:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
0041:         * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0042:         *
0043:         * ====================================================================
0044:         * 
0045:         * This software consists of voluntary contributions made by many
0046:         * individuals on behalf of Collab.Net.
0047:         */
0048:
0049:        // JDK classes
0050:        import com.workingdogs.village.DataSetException;
0051:        import java.util.List;
0052:        import java.util.Iterator;
0053:        import java.util.LinkedList;
0054:        import java.util.Collections;
0055:        import java.util.ArrayList;
0056:        import java.util.Map;
0057:        import java.util.HashMap;
0058:        import java.util.Locale;
0059:        import java.util.Vector;
0060:
0061:        import org.apache.regexp.RECompiler;
0062:        import org.apache.regexp.REProgram;
0063:        import org.apache.regexp.RESyntaxException;
0064:        import com.workingdogs.village.Record;
0065:
0066:        // Turbine classes
0067:        import org.apache.torque.NoRowsException;
0068:        import org.apache.torque.TorqueException;
0069:        import org.apache.torque.om.ComboKey;
0070:        import org.apache.torque.om.SimpleKey;
0071:        import org.apache.torque.om.BaseObject;
0072:        import org.apache.torque.manager.MethodResultCache;
0073:        import org.apache.torque.util.Criteria;
0074:        import org.apache.fulcrum.security.entity.Group;
0075:        import org.apache.fulcrum.localization.Localization;
0076:        import org.apache.turbine.Turbine;
0077:        import org.tigris.scarab.tools.localization.L10NKey;
0078:
0079:        // Scarab classes
0080:        import org.tigris.scarab.tools.localization.L10NKeySet;
0081:        import org.tigris.scarab.tools.localization.L10NMessage;
0082:        import org.tigris.scarab.tools.localization.Localizable;
0083:        import org.tigris.scarab.util.ScarabException;
0084:        import org.tigris.scarab.util.ValidationException;
0085:        import org.tigris.scarab.util.ScarabConstants;
0086:        import org.tigris.scarab.services.security.ScarabSecurity;
0087:        import org.tigris.scarab.services.cache.ScarabCache;
0088:        import org.tigris.scarab.workflow.WorkflowFactory;
0089:        import org.tigris.scarab.reports.ReportBridge;
0090:
0091:        /**
0092:         * <p>
0093:         * The ScarabModule class is the focal point for dealing with
0094:         * Modules. It implements the concept of a Module which is a
0095:         * single module and is the base interface for all Modules. In code,
0096:         * one should <strong>never reference ScarabModule directly</strong>
0097:         * -- use its Module interface instead.  This allows us to swap
0098:         * out Module implementations by modifying the Scarab.properties
0099:         * file.
0100:         * </p>
0101:         * 
0102:         * <p>This class is the base class for 
0103:         * <code>org.tigris.scarab.om.ScarabModule</code>. BaseScarabModule extends
0104:         * this class and that definition is defined in the scarab-schema.xml
0105:         * which is used by Torque to generated BaseScarabModule.</p>
0106:         *
0107:         * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
0108:         * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
0109:         * @version $Id: AbstractScarabModule.java 10382 2006-12-13 17:02:35Z dabbous $
0110:         */
0111:        public abstract class AbstractScarabModule extends BaseObject implements 
0112:                Module, Comparable {
0113:            private static int moduleCodeLength;
0114:            // the following Strings are method names that are used in caching results
0115:            protected static final String GET_R_MODULE_ATTRIBUTES = "getRModuleAttributes";
0116:            protected static final String GET_DEDUPE_GROUPS_WITH_ATTRIBUTES = "getDedupeGroupsWithAttributes";
0117:            protected static final String GET_SAVED_REPORTS = "getSavedReports";
0118:            protected static final String GET_DEFAULT_RMODULE_USERATTRIBUTES = "getDefaultRModuleUserAttributes";
0119:            protected static final String GET_ISSUE_TYPES = "getIssueTypes";
0120:            protected static final String GET_NAV_ISSUE_TYPES = "getNavIssueTypes";
0121:            protected static final String GET_ALL_R_MODULE_OPTIONS = "getAllRModuleOptions";
0122:            protected static final String GET_LEAF_R_MODULE_OPTIONS = "getLeafRModuleOptions";
0123:            protected static final String GET_R_MODULE_ISSUE_TYPES = "getRModuleIssueTypes";
0124:            protected static final String GET_R_MODULE_ISSUE_TYPE = "getRModuleIssueType";
0125:            protected static final String GET_TEMPLATE_TYPES = "getTemplateTypes";
0126:            protected static final String GET_UNAPPROVED_QUERIES = "getUnapprovedQueries";
0127:            protected static final String GET_UNAPPROVED_TEMPLATES = "getUnapprovedTemplates";
0128:            protected static final String GET_AVAILABLE_ISSUE_TYPES = "getAvailableIssueTypes";
0129:
0130:            private static final L10NKey VALIDATION_MESSAGE = new L10NKey(
0131:                    "ModuleValidationMessage");
0132:
0133:            private List parentModules = null;
0134:
0135:            /** set to true while the setInitialAttributesAndIssueTypes() method is in process */
0136:            private boolean isInitializing = false;
0137:
0138:            /**
0139:             * Should be called when the parentage is modified.
0140:             */
0141:            protected void resetAncestors() {
0142:                parentModules = null;
0143:            }
0144:
0145:            /**
0146:             * The 'long' name of the module, includes the parents.
0147:             */
0148:            private String name = null;
0149:
0150:            /**
0151:             * @see org.tigris.scarab.om.Module#getUsers(String)
0152:             */
0153:            public abstract ScarabUser[] getUsers(String permission)
0154:                    throws TorqueException;
0155:
0156:            /**
0157:             * @see org.tigris.scarab.om.Module#getUsers(String)
0158:             */
0159:            public abstract ScarabUser[] getUsers(List permissions)
0160:                    throws TorqueException;
0161:
0162:            /**
0163:             * @return The unadorned real name of this module; never
0164:             * <code>null</code>.
0165:             * @see #getName()
0166:             */
0167:            public abstract String getRealName();
0168:
0169:            public abstract Integer getModuleId();
0170:
0171:            /**
0172:             * This method is an implementation of the Group.getName() method
0173:             * and returns a module along with its ancestors
0174:             */
0175:            public String getName() {
0176:                if (name == null) {
0177:                    boolean isRoot = getModuleId().equals(ROOT_ID);
0178:                    if (isRoot) {
0179:                        return getRealName();
0180:                    }
0181:                    StringBuffer sb = new StringBuffer();
0182:                    List parents = null;
0183:                    try {
0184:                        parents = getAncestors();
0185:                    } catch (Exception e) {
0186:                        e.printStackTrace();
0187:                        getLog().error(e);
0188:                        return null;
0189:                    }
0190:                    Iterator itr = parents.iterator();
0191:                    boolean firstTime = true;
0192:                    while (itr.hasNext()) {
0193:                        Module me = (Module) itr.next();
0194:                        if (!firstTime) {
0195:                            sb.append(NAME_DELIMINATOR.getMessage());
0196:                        }
0197:                        sb.append(me.getRealName());
0198:                        firstTime = false;
0199:                    }
0200:                    // Make sure we have parents and if we are root, 
0201:                    // don't show ourselves again.
0202:                    if (parents.size() >= 1 && !isRoot) {
0203:                        sb.append(NAME_DELIMINATOR.getMessage());
0204:                    }
0205:                    // If we are root, don't show ourselves again.
0206:                    if (!isRoot) {
0207:                        sb.append(getRealName());
0208:                    }
0209:                    name = sb.toString();
0210:                }
0211:                return name;
0212:            }
0213:
0214:            /**
0215:             * This method is an implementation of the Group.setName() method
0216:             */
0217:            public void setName(String name) {
0218:                this .name = name;
0219:            }
0220:
0221:            /**
0222:             * Creates a new Issue.
0223:             */
0224:            public Issue getNewIssue(IssueType issueType)
0225:                    throws TorqueException {
0226:                Issue issue = Issue.getNewInstance(this , issueType);
0227:                issue.setDeleted(false);
0228:                return issue;
0229:            }
0230:
0231:            /**
0232:             * Returns this ModuleEntities ancestors in ascending order. 
0233:             * It does not return the 0 parent though.
0234:             */
0235:            public synchronized List getAncestors() throws TorqueException {
0236:                if (parentModules == null) {
0237:                    parentModules = new ArrayList();
0238:                    Module parent = getParent();
0239:                    if (parent != null && !parent.getModuleId().equals(ROOT_ID)
0240:                            && !isEndlessLoop(parent)) {
0241:                        addAncestors(parent);
0242:                    }
0243:                }
0244:                return parentModules;
0245:            }
0246:
0247:            /**
0248:             * recursive helper method for getAncestors()
0249:             */
0250:            private void addAncestors(Module module) throws TorqueException {
0251:                if (!module.getParentId().equals(ROOT_ID)) {
0252:                    addAncestors(module.getParent());
0253:                }
0254:                parentModules.add(module);
0255:            }
0256:
0257:            /**
0258:             * check for endless loops where Module A > Module B > Module A
0259:             */
0260:            public boolean isEndlessLoop(Module parent) throws TorqueException {
0261:                if (parent.getModuleId() != ROOT_ID) {
0262:                    Module parentParent = parent.getParent();
0263:                    if (parentParent != null && parentParent == this ) {
0264:                        return true;
0265:                    }
0266:                }
0267:                return false;
0268:            }
0269:
0270:            /**
0271:             * Creates new attribute group.
0272:             */
0273:            public AttributeGroup createNewGroup(IssueType issueType)
0274:                    throws TorqueException {
0275:                return issueType.createNewGroup(this );
0276:            }
0277:
0278:            /**
0279:             * This method is used within Wizard1.vm to get a list of attribute
0280:             * groups which are marked as dedupe and have a list of attributes
0281:             * in them.
0282:             */
0283:            public List getDedupeGroupsWithAttributes(IssueType issueType)
0284:                    throws TorqueException {
0285:                List result = null;
0286:                if (issueType == null) {
0287:                    result = new Vector(0);
0288:                } else {
0289:                    Object obj = getMethodResult().get(this ,
0290:                            GET_DEDUPE_GROUPS_WITH_ATTRIBUTES, issueType);
0291:                    if (obj == null) {
0292:                        List attributeGroups = issueType.getAttributeGroups(
0293:                                this , true);
0294:                        result = new ArrayList(attributeGroups.size());
0295:                        for (Iterator itr = attributeGroups.iterator(); itr
0296:                                .hasNext();) {
0297:                            AttributeGroup ag = (AttributeGroup) itr.next();
0298:                            if (ag.getDedupe() && !ag.getAttributes().isEmpty()) {
0299:                                result.add(ag);
0300:                            }
0301:                        }
0302:                        getMethodResult().put(result, this ,
0303:                                GET_DEDUPE_GROUPS_WITH_ATTRIBUTES, issueType);
0304:                    } else {
0305:                        result = (List) obj;
0306:                    }
0307:                }
0308:                return result;
0309:            }
0310:
0311:            /**
0312:             * List of active dedupe attribute groups associated with this module.
0313:             */
0314:            public List getDedupeAttributeGroups(IssueType issueType)
0315:                    throws TorqueException {
0316:                return getDedupeAttributeGroups(issueType, true);
0317:            }
0318:
0319:            /**
0320:             * List of attribute groups associated with this module.
0321:             */
0322:            public List getDedupeAttributeGroups(IssueType issueType,
0323:                    boolean activeOnly) throws TorqueException {
0324:                List groups = issueType.getAttributeGroups(this , activeOnly);
0325:                List dedupeGroups = new ArrayList();
0326:                for (int i = 0; i < groups.size(); i++) {
0327:                    AttributeGroup group = (AttributeGroup) groups.get(i);
0328:                    if (group.getDedupe()) {
0329:                        dedupeGroups.add(group);
0330:                    }
0331:                }
0332:                return dedupeGroups;
0333:            }
0334:
0335:            /**
0336:             * Gets the sequence where the dedupe screen fits between groups.
0337:             */
0338:            public int getDedupeSequence(IssueType issueType)
0339:                    throws TorqueException {
0340:                return issueType.getDedupeSequence(this );
0341:            }
0342:
0343:            public ScarabUser[] getEligibleIssueReporters()
0344:                    throws TorqueException {
0345:                return getUsers(ScarabSecurity.ISSUE__ENTER);
0346:            }
0347:
0348:            /**
0349:             * The users who are possible candidates as values for the given
0350:             * attribute.  An eligible user is determined by checking for users that
0351:             * have the permission associated with the attribute.
0352:             *
0353:             * @param attribute an <code>Attribute</code> value
0354:             * @return a <code>ScarabUser[]</code> value
0355:             * @exception ScarabException if the attribute has no associated permission
0356:             * @exception Exception if an error occurs
0357:             */
0358:            public ScarabUser[] getEligibleUsers(Attribute attribute)
0359:                    throws TorqueException, ScarabException {
0360:                ScarabUser[] users = null;
0361:                if (attribute.isUserAttribute()) {
0362:                    String permission = attribute.getPermission();
0363:                    if (permission == null) {
0364:                        throw new ScarabException(
0365:                                L10NKeySet.ExceptionNoAttributePermission,
0366:                                attribute.getName());
0367:                    } else {
0368:                        users = getUsers(permission);
0369:                    }
0370:                }
0371:                return users;
0372:            }
0373:
0374:            /**
0375:             * Set this module's immediate parent module
0376:             */
0377:            public abstract void setParent(Module v) throws TorqueException;
0378:
0379:            /**
0380:             * Get this module's immediate parent module
0381:             */
0382:            public abstract Module getParent() throws TorqueException;
0383:
0384:            /**
0385:             * List of saved reports associated with this module and
0386:             * created by this user.
0387:             */
0388:            public List getSavedReports(final ScarabUser user)
0389:                    throws TorqueException, ScarabException {
0390:                List reports = null;
0391:                final Object obj = ScarabCache.get(this , GET_SAVED_REPORTS,
0392:                        user);
0393:                if (obj == null) {
0394:                    final Criteria crit = new Criteria().add(
0395:                            ReportPeer.DELETED, 0);
0396:                    final Criteria.Criterion cc = crit.getNewCriterion(
0397:                            ReportPeer.SCOPE_ID, Scope.MODULE__PK,
0398:                            Criteria.EQUAL);
0399:                    cc.and(crit.getNewCriterion(ReportPeer.MODULE_ID,
0400:                            getModuleId(), Criteria.EQUAL));
0401:                    final Criteria.Criterion personalcc = crit.getNewCriterion(
0402:                            ReportPeer.SCOPE_ID, Scope.PERSONAL__PK,
0403:                            Criteria.EQUAL);
0404:                    personalcc.and(crit.getNewCriterion(ReportPeer.USER_ID,
0405:                            user.getUserId(), Criteria.EQUAL));
0406:                    final Criteria.Criterion personalmodulecc = crit
0407:                            .getNewCriterion(ReportPeer.MODULE_ID,
0408:                                    getModuleId(), Criteria.EQUAL);
0409:                    personalmodulecc.or(crit.getNewCriterion(
0410:                            ReportPeer.MODULE_ID, null, Criteria.EQUAL));
0411:                    personalcc.and(personalmodulecc);
0412:                    cc.or(personalcc);
0413:                    crit.add(cc);
0414:                    crit.addAscendingOrderByColumn(ReportPeer.SCOPE_ID);
0415:                    final List torqueReports = ReportPeer.doSelect(crit);
0416:                    // create ReportBridge's from torque Reports.
0417:                    if (!torqueReports.isEmpty()) {
0418:                        reports = new ArrayList(torqueReports.size());
0419:                        for (Iterator i = torqueReports.iterator(); i.hasNext();) {
0420:                            final Report torqueReport = (Report) i.next();
0421:                            try {
0422:                                reports.add(new ReportBridge(torqueReport));
0423:                            } catch (org.xml.sax.SAXException e) {
0424:                                getLog()
0425:                                        .warn(
0426:                                                "Could not parse the report id="
0427:                                                        + torqueReport
0428:                                                                .getReportId()
0429:                                                        + ", so it has been marked as deleted.");
0430:                                torqueReport.setDeleted(true);
0431:                                torqueReport.save();
0432:                            } catch (Exception e) {
0433:                                throw new ScarabException(
0434:                                        L10NKeySet.ExceptionGeneral, e);
0435:                            }
0436:                        }
0437:                    } else {
0438:                        reports = Collections.EMPTY_LIST;
0439:                    }
0440:
0441:                    ScarabCache.put(reports, this , GET_SAVED_REPORTS, user);
0442:                } else {
0443:                    reports = (List) obj;
0444:                }
0445:                return reports;
0446:            }
0447:
0448:            /**
0449:             * Gets a list of attributes for this module with a specific
0450:             * issue type.
0451:             */
0452:            public List getAttributes(final IssueType issueType)
0453:                    throws TorqueException {
0454:                final Criteria crit = new Criteria();
0455:                crit.add(RModuleAttributePeer.ISSUE_TYPE_ID, issueType
0456:                        .getIssueTypeId());
0457:                return getAttributes(crit);
0458:            }
0459:
0460:            /**
0461:             * gets a list of all of the Attributes in a Module based on the Criteria.
0462:             */
0463:            public List getAttributes(final Criteria criteria)
0464:                    throws TorqueException {
0465:                final List moduleAttributes = getRModuleAttributes(criteria);
0466:                final List attributes = new ArrayList(moduleAttributes.size());
0467:                for (int i = 0; i < moduleAttributes.size(); i++) {
0468:                    attributes.add(((RModuleAttribute) moduleAttributes.get(i))
0469:                            .getAttribute());
0470:                }
0471:                return attributes;
0472:            }
0473:
0474:            /**
0475:             * gets a list of all of the User Attributes in a Module.
0476:             */
0477:            public List getUserAttributes(IssueType issueType)
0478:                    throws TorqueException {
0479:                return getUserAttributes(issueType, true);
0480:            }
0481:
0482:            /**
0483:             * gets a list of all of the User Attributes in a Module.
0484:             */
0485:            public List getUserAttributes(IssueType issueType,
0486:                    boolean activeOnly) throws TorqueException {
0487:                List rModuleAttributes = getRModuleAttributes(issueType,
0488:                        activeOnly, USER);
0489:                List userAttributes = new ArrayList();
0490:
0491:                for (int i = 0; i < rModuleAttributes.size(); i++) {
0492:                    Attribute att = ((RModuleAttribute) rModuleAttributes
0493:                            .get(i)).getAttribute();
0494:                    userAttributes.add(att);
0495:                }
0496:                return userAttributes;
0497:            }
0498:
0499:            /**
0500:             * gets a list of permissions associated with the User Attributes
0501:             * that are active for this Module.
0502:             */
0503:            public List getUserPermissions(IssueType issueType)
0504:                    throws TorqueException {
0505:                List userAttrs = getUserAttributes(issueType, true);
0506:                List permissions = new ArrayList();
0507:                for (int i = 0; i < userAttrs.size(); i++) {
0508:                    String permission = ((Attribute) userAttrs.get(i))
0509:                            .getPermission();
0510:                    if (!permissions.contains(permission)) {
0511:                        permissions.add(permission);
0512:                    }
0513:                }
0514:                return permissions;
0515:            }
0516:
0517:            /**
0518:             * FIXME: can this be done more efficently?
0519:             * gets highest sequence number for module-attribute map
0520:             * so that a new RModuleAttribute can be added at the end.
0521:             */
0522:            public int getLastAttribute(IssueType issueType,
0523:                    String attributeType) throws TorqueException {
0524:                List moduleAttributes = getRModuleAttributes(issueType, false,
0525:                        attributeType);
0526:                int last = 0;
0527:
0528:                for (int i = 0; i < moduleAttributes.size(); i++) {
0529:                    int order = ((RModuleAttribute) moduleAttributes.get(i))
0530:                            .getOrder();
0531:                    if (order > last) {
0532:                        last = order;
0533:                    }
0534:                }
0535:                return last;
0536:            }
0537:
0538:            /**
0539:             * FIXME: can this be done more efficently?
0540:             * gets highest sequence number for module-attribute map
0541:             * so that a new RModuleAttribute can be added at the end.
0542:             */
0543:            public int getLastAttributeOption(Attribute attribute,
0544:                    IssueType issueType) throws TorqueException {
0545:                List moduleOptions = getRModuleOptions(attribute, issueType);
0546:                int last = 0;
0547:                for (int i = 0; i < moduleOptions.size(); i++) {
0548:                    int order = ((RModuleOption) moduleOptions.get(i))
0549:                            .getOrder();
0550:                    if (order > last) {
0551:                        last = order;
0552:                    }
0553:                }
0554:                return last;
0555:            }
0556:
0557:            /*
0558:             * shift all the module options by 1 for all the non-active options with 
0559:             * an order higher or equal than offset
0560:             */
0561:            public void shiftAttributeOption(Attribute attribute,
0562:                    IssueType issueType, int offset) throws TorqueException {
0563:                List moduleOptions = getRModuleOptions(attribute, issueType,
0564:                        false);
0565:                RModuleOption rmo;
0566:                for (int i = 0; i < moduleOptions.size(); i++) {
0567:                    rmo = (RModuleOption) moduleOptions.get(i);
0568:                    int order = rmo.getOrder();
0569:                    if (order >= offset && !rmo.getActive()) {
0570:                        rmo.setOrder(order + 1);
0571:                        rmo.save();
0572:                    }
0573:                }
0574:            }
0575:
0576:            /**
0577:             * gets a list of all of the global Attributes that are not 
0578:             * associated with this module and issue type
0579:             */
0580:            public List getAvailableAttributes(IssueType issueType,
0581:                    String attributeType) throws TorqueException {
0582:                List allAttributes = AttributePeer.getAttributes(attributeType);
0583:                List availAttributes = new ArrayList();
0584:                List rModuleAttributes = getRModuleAttributes(issueType, false,
0585:                        attributeType);
0586:                List moduleAttributes = new ArrayList();
0587:                if (rModuleAttributes.isEmpty()) {
0588:                    availAttributes = allAttributes;
0589:                } else {
0590:                    for (int i = 0; i < rModuleAttributes.size(); i++) {
0591:                        moduleAttributes
0592:                                .add(((RModuleAttribute) rModuleAttributes
0593:                                        .get(i)).getAttribute());
0594:                    }
0595:
0596:                    for (int i = 0; i < allAttributes.size(); i++) {
0597:                        Attribute att = (Attribute) allAttributes.get(i);
0598:                        if (!moduleAttributes.contains(att)) {
0599:                            availAttributes.add(att);
0600:                        }
0601:                    }
0602:                }
0603:                return availAttributes;
0604:            }
0605:
0606:            /**
0607:             * gets a list of all of the Attribute options that are not
0608:             * associated with this module and attribute.
0609:             */
0610:            public List getAvailableAttributeOptions(Attribute attribute,
0611:                    IssueType issueType) throws TorqueException {
0612:                List rModuleOptions = getRModuleOptions(attribute, issueType,
0613:                        false);
0614:                List moduleOptions = new ArrayList();
0615:                if (rModuleOptions != null) {
0616:                    for (int i = 0; i < rModuleOptions.size(); i++) {
0617:                        moduleOptions.add(((RModuleOption) rModuleOptions
0618:                                .get(i)).getAttributeOption());
0619:                    }
0620:                }
0621:
0622:                List allOptions = attribute.getAttributeOptions(true);
0623:                List availOptions = new ArrayList();
0624:
0625:                for (int i = 0; i < allOptions.size(); i++) {
0626:                    AttributeOption option = (AttributeOption) allOptions
0627:                            .get(i);
0628:                    if (!moduleOptions.contains(option) && !option.getDeleted()) {
0629:                        availOptions.add(option);
0630:                    }
0631:                }
0632:                return availOptions;
0633:            }
0634:
0635:            /**
0636:             * Returns default issue list attributes for this module.
0637:             */
0638:            public List getDefaultRModuleUserAttributes(IssueType issueType)
0639:                    throws TorqueException {
0640:                List result = null;
0641:                Object obj = ScarabCache.get(this ,
0642:                        GET_DEFAULT_RMODULE_USERATTRIBUTES, issueType);
0643:                if (obj == null) {
0644:                    result = new LinkedList();
0645:                    Attribute[] attributes = new Attribute[3];
0646:                    int count = 0;
0647:                    attributes[count++] = issueType
0648:                            .getDefaultTextAttribute(this );
0649:                    if (attributes[0] == null) {
0650:                        count = 0;
0651:                    }
0652:                    List rma1s = getRModuleAttributes(issueType, true, NON_USER);
0653:                    Iterator i = rma1s.iterator();
0654:                    while (i.hasNext()) {
0655:                        Attribute a = ((RModuleAttribute) i.next())
0656:                                .getAttribute();
0657:                        if (!a.isTextAttribute() || attributes[0] == null) {
0658:                            attributes[count++] = a;
0659:                            break;
0660:                        }
0661:                    }
0662:
0663:                    List rma2s = getRModuleAttributes(issueType, true, USER);
0664:                    i = rma2s.iterator();
0665:                    while (i.hasNext() && count < 3) {
0666:                        Attribute a = ((RModuleAttribute) i.next())
0667:                                .getAttribute();
0668:                        attributes[count++] = a;
0669:                    }
0670:
0671:                    // if we still have less than 3 attributes, give the non user
0672:                    // attributes another try
0673:                    i = rma1s.iterator();
0674:                    while (i.hasNext() && count < 3) {
0675:                        Attribute a = ((RModuleAttribute) i.next())
0676:                                .getAttribute();
0677:                        if (!a.equals(attributes[0])
0678:                                && !a.equals(attributes[1])) {
0679:                            attributes[count++] = a;
0680:                        }
0681:                    }
0682:
0683:                    for (int j = 0; j < attributes.length; j++) {
0684:                        if (attributes[j] != null) {
0685:                            RModuleUserAttribute rmua = RModuleUserAttributeManager
0686:                                    .getInstance();
0687:                            rmua.setAttribute(attributes[j]);
0688:                            rmua.setIssueType(issueType);
0689:                            rmua.setOrder(j + 1);
0690:                            result.add(rmua);
0691:                        }
0692:                    }
0693:                    ScarabCache.put(result, this ,
0694:                            GET_DEFAULT_RMODULE_USERATTRIBUTES, issueType);
0695:                } else {
0696:                    result = (List) obj;
0697:                }
0698:                return result;
0699:            }
0700:
0701:            /**
0702:             * This method is useful for getting an issue object
0703:             * by a String id. It has some logic in it for appending
0704:             * the Module Code as well as stripping spaces off the
0705:             * id value using the String.trim() method.
0706:             * @deprecated use IssueManager.getIssueById(String id, String defaultCode)
0707:             */
0708:            public Issue getIssueById(String id) throws TorqueException {
0709:                return IssueManager.getIssueById(id, getCode());
0710:            }
0711:
0712:            /**
0713:             * gets a list of the Issue Types for this module. only shows
0714:             * active issue types
0715:             */
0716:            public List getIssueTypes() throws TorqueException {
0717:                return getIssueTypes(true);
0718:            }
0719:
0720:            /**
0721:             * gets a list of the Issue Types for this module. only shows
0722:             * active issue types
0723:             */
0724:            public List getIssueTypes(boolean activeOnly)
0725:                    throws TorqueException {
0726:                List types = null;
0727:                Boolean activeOnlyValue = activeOnly ? Boolean.TRUE
0728:                        : Boolean.FALSE;
0729:                Object obj = ScarabCache.get(this , GET_ISSUE_TYPES,
0730:                        activeOnlyValue);
0731:                if (obj == null) {
0732:                    Criteria crit = new Criteria();
0733:                    crit.addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
0734:                            IssueTypePeer.ISSUE_TYPE_ID);
0735:                    crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId());
0736:                    if (activeOnly) {
0737:                        crit.add(RModuleIssueTypePeer.ACTIVE, true);
0738:                    }
0739:                    crit.add(IssueTypePeer.PARENT_ID, 0);
0740:                    crit.add(IssueTypePeer.DELETED, 0);
0741:                    crit
0742:                            .addAscendingOrderByColumn(RModuleIssueTypePeer.PREFERRED_ORDER);
0743:                    types = IssueTypePeer.doSelect(crit);
0744:                    ScarabCache.put(types, this , "getIssueTypes",
0745:                            activeOnlyValue);
0746:                } else {
0747:                    types = (List) obj;
0748:                }
0749:                return types;
0750:            }
0751:
0752:            /**
0753:             * gets a list of the Issue Types for this module.
0754:             * that get listed in the left navigation. only shows active issue types.
0755:             */
0756:            public List getNavIssueTypes() throws TorqueException {
0757:                List types = null;
0758:                Object obj = getMethodResult().get(this , GET_NAV_ISSUE_TYPES);
0759:                if (obj == null) {
0760:                    Criteria crit = new Criteria();
0761:                    crit.addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
0762:                            IssueTypePeer.ISSUE_TYPE_ID);
0763:                    crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId());
0764:                    crit.add(RModuleIssueTypePeer.ACTIVE, true);
0765:                    crit.add(RModuleIssueTypePeer.DISPLAY, true);
0766:                    crit.add(IssueTypePeer.PARENT_ID, 0);
0767:                    crit.add(IssueTypePeer.DELETED, 0);
0768:                    crit
0769:                            .addAscendingOrderByColumn(RModuleIssueTypePeer.PREFERRED_ORDER);
0770:                    types = IssueTypePeer.doSelect(crit);
0771:                    getMethodResult().put(types, this , GET_NAV_ISSUE_TYPES);
0772:                } else {
0773:                    types = (List) obj;
0774:                }
0775:                return types;
0776:            }
0777:
0778:            /**
0779:             * gets a list of all of the issue types that are not associated with 
0780:             * this module
0781:             */
0782:            public List getAvailableIssueTypes() throws TorqueException {
0783:                List availIssueTypes = null;
0784:                Object obj = ScarabCache.get(this , GET_AVAILABLE_ISSUE_TYPES);
0785:                if (obj == null) {
0786:                    availIssueTypes = new ArrayList();
0787:                    List allIssueTypes = IssueTypePeer.getAllIssueTypes(false);
0788:                    List currentIssueTypes = getIssueTypes(false);
0789:                    Iterator iter = allIssueTypes.iterator();
0790:                    while (iter.hasNext()) {
0791:                        IssueType issueType = (IssueType) iter.next();
0792:                        if (IssueTypePeer.getRootKey().equals(
0793:                                issueType.getParentId())
0794:                                && !IssueTypePeer.getRootKey().equals(
0795:                                        issueType.getIssueTypeId())
0796:                                && !currentIssueTypes.contains(issueType)) {
0797:                            availIssueTypes.add(issueType);
0798:                        }
0799:                    }
0800:                    ScarabCache.put(availIssueTypes, this ,
0801:                            GET_AVAILABLE_ISSUE_TYPES);
0802:                } else {
0803:                    availIssueTypes = (List) obj;
0804:                }
0805:                return availIssueTypes;
0806:            }
0807:
0808:            /** 
0809:             * Returns RModuleAttributes associated with this module through the
0810:             * foreign key in the schema. This method will return an empty list, if the
0811:             * RModuleAttributes are inherited from its parent.  Will not return an
0812:             * RModuleAttribute if the Attribute is deleted. NOTE: Do not try to add caching
0813:             * to this method as it seems to break things when an attribute is changed on
0814:             * an existing issue. (JSS)
0815:             */
0816:            public List getRModuleAttributes(Criteria crit)
0817:                    throws TorqueException {
0818:                crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
0819:                crit.addJoin(RModuleAttributePeer.ATTRIBUTE_ID,
0820:                        AttributePeer.ATTRIBUTE_ID);
0821:                crit.add(AttributePeer.DELETED, false);
0822:                return RModuleAttributePeer.doSelect(crit);
0823:            }
0824:
0825:            /**
0826:             * Overridden method.
0827:             */
0828:            public abstract List getRModuleOptions(Criteria crit)
0829:                    throws TorqueException;
0830:
0831:            /**
0832:             * Adds module-attribute mapping to module.
0833:             */
0834:            public RModuleAttribute addRModuleAttribute(
0835:                    final IssueType issueType, final Attribute attribute)
0836:                    throws TorqueException, ScarabException {
0837:                String attributeType = null;
0838:                attributeType = (attribute.isUserAttribute() ? USER : NON_USER);
0839:
0840:                final RModuleAttribute rma = new RModuleAttribute();
0841:                rma.setModuleId(getModuleId());
0842:                rma.setIssueTypeId(issueType.getIssueTypeId());
0843:                rma.setAttributeId(attribute.getAttributeId());
0844:                rma.setOrder(getLastAttribute(issueType, attributeType) + 1);
0845:                rma.setConditionsArray(attribute.getConditionsArray());
0846:                rma.save();
0847:                getRModuleAttributes(issueType, false, attributeType).add(rma);
0848:
0849:                // Add to template type
0850:                final IssueType templateType = IssueTypeManager.getInstance(
0851:                        issueType.getTemplateId(), false);
0852:                final RModuleAttribute rma2 = new RModuleAttribute();
0853:                rma2.setModuleId(getModuleId());
0854:                rma2.setIssueTypeId(templateType.getIssueTypeId());
0855:                rma2.setAttributeId(attribute.getAttributeId());
0856:                rma2
0857:                        .setOrder(getLastAttribute(templateType, attributeType) + 1);
0858:                rma2.save();
0859:                return rma;
0860:            }
0861:
0862:            /**
0863:             * Adds module-attribute-option mapping to module.
0864:             */
0865:            public RModuleOption addRModuleOption(IssueType issueType,
0866:                    AttributeOption option) throws TorqueException {
0867:                RModuleOption rmo = new RModuleOption();
0868:                rmo.setModuleId(getModuleId());
0869:                rmo.setIssueTypeId(issueType.getIssueTypeId());
0870:                rmo.setOptionId(option.getOptionId());
0871:                rmo.setDisplayValue(option.getName());
0872:                rmo.setOrder(getLastAttributeOption(option.getAttribute(),
0873:                        issueType) + 1);
0874:                return rmo;
0875:            }
0876:
0877:            public RModuleAttribute getRModuleAttribute(Attribute attribute,
0878:                    IssueType issueType) throws TorqueException {
0879:                RModuleAttribute rma = null;
0880:                if (attribute != null && issueType != null) {
0881:                    List rmas = null;
0882:                    if (attribute.isUserAttribute()) {
0883:                        rmas = getRModuleAttributes(issueType, false, USER);
0884:                    } else {
0885:                        rmas = getRModuleAttributes(issueType, false, NON_USER);
0886:                    }
0887:                    Iterator i = rmas.iterator();
0888:                    while (i.hasNext()) {
0889:                        rma = (RModuleAttribute) i.next();
0890:                        if (rma.getAttribute().equals(attribute)) {
0891:                            break;
0892:                        } else {
0893:                            rma = null;
0894:                        }
0895:                    }
0896:                }
0897:                return rma;
0898:            }
0899:
0900:            /**
0901:             * Overridden method. Calls the super method and if no results are returned
0902:             * the call is passed on to the parent module.
0903:             */
0904:            public List getRModuleAttributes(IssueType issueType)
0905:                    throws TorqueException {
0906:                return getRModuleAttributes(issueType, false);
0907:            }
0908:
0909:            /**
0910:             * Returns true if module has attributes associated with issue type.
0911:             */
0912:            public boolean hasAttributes(final IssueType issueType)
0913:                    throws TorqueException, DataSetException {
0914:                final Criteria crit = new Criteria();
0915:                crit.add(RModuleAttributePeer.ISSUE_TYPE_ID, issueType
0916:                        .getIssueTypeId());
0917:                crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
0918:                crit.addSelectColumn("count("
0919:                        + RModuleAttributePeer.ATTRIBUTE_ID + ")");
0920:                return ((Record) IssuePeer.doSelectVillageRecords(crit).get(0))
0921:                        .getValue(1).asInt() > 0;
0922:            }
0923:
0924:            /**
0925:             * Overridden method.  Calls the super method and if no results are
0926:             * returned the call is passed on to the parent module.
0927:             */
0928:            public List getRModuleAttributes(IssueType issueType,
0929:                    boolean activeOnly) throws TorqueException {
0930:                return getRModuleAttributes(issueType, activeOnly, "all");
0931:            }
0932:
0933:            public List getRModuleAttributes(IssueType issueType,
0934:                    boolean activeOnly, String attributeType)
0935:                    throws TorqueException {
0936:                List rmas = null;
0937:                Boolean activeBool = (activeOnly ? Boolean.TRUE : Boolean.FALSE);
0938:                Object obj = getMethodResult().get(this ,
0939:                        GET_R_MODULE_ATTRIBUTES, issueType, activeBool,
0940:                        attributeType);
0941:                if (obj == null) {
0942:                    Criteria crit = new Criteria();
0943:                    crit.add(RModuleAttributePeer.ISSUE_TYPE_ID, issueType
0944:                            .getIssueTypeId());
0945:                    crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
0946:                    crit
0947:                            .addAscendingOrderByColumn(RModuleAttributePeer.PREFERRED_ORDER);
0948:                    crit
0949:                            .addAscendingOrderByColumn(RModuleAttributePeer.DISPLAY_VALUE);
0950:
0951:                    if (activeOnly) {
0952:                        crit.add(RModuleAttributePeer.ACTIVE, true);
0953:                    }
0954:
0955:                    crit.addJoin(AttributePeer.ATTRIBUTE_ID,
0956:                            RModuleAttributePeer.ATTRIBUTE_ID);
0957:                    if (USER.equals(attributeType)) {
0958:                        crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
0959:                                AttributeTypePeer.USER_TYPE_KEY);
0960:                    } else if (NON_USER.equals(attributeType)) {
0961:                        crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
0962:                                AttributeTypePeer.USER_TYPE_KEY,
0963:                                Criteria.NOT_EQUAL);
0964:                    }
0965:
0966:                    rmas = RModuleAttributePeer.doSelect(crit);
0967:                    getMethodResult().put(rmas, this , GET_R_MODULE_ATTRIBUTES,
0968:                            issueType, activeBool, attributeType);
0969:                } else {
0970:                    rmas = (List) obj;
0971:                }
0972:                return rmas;
0973:            }
0974:
0975:            /**
0976:             * gets a list of all of the Attributes in this module.
0977:             */
0978:            public List getAllAttributes() throws TorqueException {
0979:                return getAttributes(new Criteria());
0980:            }
0981:
0982:            /**
0983:             * Return the list of option attributes (ATTRIBUTE_ID=5).
0984:             * @return
0985:             * @throws TorqueException
0986:             */
0987:            public List getAllOptionAttributes() throws TorqueException {
0988:                Criteria crit = new Criteria();
0989:                crit.addJoin(RModuleAttributePeer.ATTRIBUTE_ID,
0990:                        AttributePeer.ATTRIBUTE_ID);
0991:                crit.add(AttributePeer.ATTRIBUTE_TYPE_ID, 5);
0992:                crit.add(AttributePeer.DELETED, false);
0993:                crit.add(RModuleAttributePeer.ACTIVE, true);
0994:                crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
0995:                crit
0996:                        .addAscendingOrderByColumn(RModuleAttributePeer.DISPLAY_VALUE);
0997:                crit.setDistinct();
0998:                List result = AttributePeer.doSelect(crit);
0999:                return result;
1000:            }
1001:
1002:            /**
1003:             * Return the list of attribute options for attribute with given attributeId.
1004:             * @return
1005:             * @throws TorqueException
1006:             * @throws ScarabException 
1007:             */
1008:            public List getAllAttributeOptions(Integer attributeId)
1009:                    throws TorqueException, ScarabException {
1010:                List result;
1011:                if (attributeId == null) {
1012:                    this 
1013:                            .getLog()
1014:                            .warn(
1015:                                    "No attribute specified while fetching attribute options.");
1016:                    result = Collections.EMPTY_LIST;
1017:                } else {
1018:                    int id = attributeId.intValue();
1019:                    Attribute attribute = Attribute.getInstance(id);
1020:                    if (attribute == null) {
1021:                        this .getLog().warn(
1022:                                "No options found for Attribute ["
1023:                                        + attributeId + "]");
1024:                        // L10NMessage msg = new
1025:                        // L10NMessage(L10NKeySet.AttributeNotInSession,""+attributeId);
1026:                        // throw new ScarabException(msg);
1027:                        result = Collections.EMPTY_LIST;
1028:                    } else {
1029:                        // Integer attributeId = attribute.getAttributeId();
1030:
1031:                        Criteria crit = new Criteria();
1032:                        crit.add(AttributeOptionPeer.ATTRIBUTE_ID, attributeId);
1033:                        crit.add(AttributeOptionPeer.DELETED, false);
1034:                        result = AttributeOptionPeer.doSelect(crit);
1035:                    }
1036:                }
1037:                return result;
1038:            }
1039:
1040:            /**
1041:             * gets a list of all of the active Attributes. ordered by name
1042:             */
1043:            public List getActiveAttributesByName(IssueType issueType,
1044:                    String attributeType) throws TorqueException {
1045:                Criteria crit = new Criteria();
1046:                crit.add(RModuleAttributePeer.MODULE_ID, getModuleId());
1047:                crit.add(RModuleAttributePeer.ISSUE_TYPE_ID, issueType
1048:                        .getIssueTypeId());
1049:                crit.addJoin(RModuleAttributePeer.ATTRIBUTE_ID,
1050:                        AttributePeer.ATTRIBUTE_ID);
1051:                crit.add(AttributePeer.DELETED, false);
1052:                crit.add(RModuleAttributePeer.ACTIVE, true);
1053:                if (USER.equals(attributeType)) {
1054:                    crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
1055:                            AttributeTypePeer.USER_TYPE_KEY);
1056:                    crit.addJoin(AttributePeer.ATTRIBUTE_ID,
1057:                            RModuleAttributePeer.ATTRIBUTE_ID);
1058:                } else if (NON_USER.equals(attributeType)) {
1059:                    crit
1060:                            .add(AttributePeer.ATTRIBUTE_TYPE_ID,
1061:                                    AttributeTypePeer.USER_TYPE_KEY,
1062:                                    Criteria.NOT_EQUAL);
1063:                }
1064:                crit
1065:                        .addAscendingOrderByColumn(RModuleAttributePeer.DISPLAY_VALUE);
1066:                return AttributePeer.doSelect(crit);
1067:            }
1068:
1069:            public List getRModuleOptions(Attribute attribute,
1070:                    IssueType issueType) throws TorqueException {
1071:                return getRModuleOptions(attribute, issueType, true);
1072:            }
1073:
1074:            public List getRModuleOptions(Attribute attribute,
1075:                    IssueType issueType, boolean activeOnly)
1076:                    throws TorqueException {
1077:                List allRModuleOptions = null;
1078:                allRModuleOptions = getAllRModuleOptions(attribute, issueType);
1079:
1080:                if (allRModuleOptions != null) {
1081:                    if (activeOnly) {
1082:                        List activeRModuleOptions = new ArrayList(
1083:                                allRModuleOptions.size());
1084:                        for (int i = 0; i < allRModuleOptions.size(); i++) {
1085:                            RModuleOption rmo = (RModuleOption) allRModuleOptions
1086:                                    .get(i);
1087:                            if (rmo.getActive()) {
1088:                                activeRModuleOptions.add(rmo);
1089:                            }
1090:                        }
1091:                        allRModuleOptions = activeRModuleOptions;
1092:                    }
1093:                }
1094:                return allRModuleOptions;
1095:            }
1096:
1097:            private List getAllRModuleOptions(Attribute attribute,
1098:                    IssueType issueType) throws TorqueException {
1099:                if (attribute == null) {
1100:                    // during initilaization of a new query, no
1101:                    // attributes are available.
1102:                    // This check avoids a NLP
1103:                    return null;
1104:                }
1105:
1106:                List rModOpts = null;
1107:                Object obj = ScarabCache.get(this , GET_ALL_R_MODULE_OPTIONS,
1108:                        attribute, issueType);
1109:                if (obj == null) {
1110:                    List options = attribute.getAttributeOptions(true);
1111:                    Integer[] optIds = null;
1112:                    if (options == null) {
1113:                        optIds = new Integer[0];
1114:                    } else {
1115:                        optIds = new Integer[options.size()];
1116:                    }
1117:                    for (int i = optIds.length - 1; i >= 0; i--) {
1118:                        optIds[i] = ((AttributeOption) options.get(i))
1119:                                .getOptionId();
1120:                    }
1121:
1122:                    if (optIds.length > 0) {
1123:                        Criteria crit = new Criteria();
1124:                        crit.add(RModuleOptionPeer.ISSUE_TYPE_ID, issueType
1125:                                .getIssueTypeId());
1126:                        crit.add(RModuleOptionPeer.MODULE_ID, getModuleId());
1127:                        crit.addIn(RModuleOptionPeer.OPTION_ID, optIds);
1128:                        crit
1129:                                .addAscendingOrderByColumn(RModuleOptionPeer.PREFERRED_ORDER);
1130:                        crit
1131:                                .addAscendingOrderByColumn(RModuleOptionPeer.DISPLAY_VALUE);
1132:                        rModOpts = getRModuleOptions(crit);
1133:                    }
1134:                    ScarabCache.put(rModOpts, this , GET_ALL_R_MODULE_OPTIONS,
1135:                            attribute, issueType);
1136:                } else {
1137:                    rModOpts = (List) obj;
1138:                }
1139:                return rModOpts;
1140:            }
1141:
1142:            public RModuleOption getRModuleOption(AttributeOption option,
1143:                    IssueType issueType) throws TorqueException {
1144:                RModuleOption rmo = null;
1145:                List rmos = getRModuleOptions(option.getAttribute(), issueType,
1146:                        false);
1147:
1148:                RModuleOption testRMO = null;
1149:                for (Iterator i = rmos.iterator(); i.hasNext();) {
1150:                    testRMO = (RModuleOption) i.next();
1151:                    if (testRMO.getAttributeOption().equals(option)) {
1152:                        rmo = testRMO;
1153:                        break;
1154:                    }
1155:                }
1156:                return rmo;
1157:            }
1158:
1159:            /**
1160:             * Gets the modules list of attribute options. Uses the
1161:             * RModuleOption table to do the join. returns null if there
1162:             * is any error.
1163:             */
1164:            public List getAttributeOptions(Attribute attribute,
1165:                    IssueType issueType) throws TorqueException {
1166:                List attributeOptions = null;
1167:                try {
1168:                    List rModuleOptions = getOptionTree(attribute, issueType,
1169:                            false);
1170:                    attributeOptions = new ArrayList(rModuleOptions.size());
1171:                    for (int i = 0; i < rModuleOptions.size(); i++) {
1172:                        attributeOptions.add(((RModuleOption) rModuleOptions
1173:                                .get(i)).getAttributeOption());
1174:                    }
1175:                } catch (Exception e) {
1176:                }
1177:                return attributeOptions;
1178:            }
1179:
1180:            public List getLeafRModuleOptions(Attribute attribute,
1181:                    IssueType issuetype) throws TorqueException {
1182:                try {
1183:                    return getLeafRModuleOptions(attribute, issuetype, true);
1184:                } catch (Exception e) {
1185:                    e.printStackTrace();
1186:                }
1187:                return null;
1188:            }
1189:
1190:            public List getLeafRModuleOptions(Attribute attribute,
1191:                    IssueType issueType, boolean activeOnly)
1192:                    throws TorqueException {
1193:                List rModOpts = null;
1194:                Boolean activeBool = (activeOnly ? Boolean.TRUE : Boolean.FALSE);
1195:                Object obj = getMethodResult().get(this ,
1196:                        GET_LEAF_R_MODULE_OPTIONS, attribute, issueType,
1197:                        activeBool);
1198:                if (obj == null) {
1199:                    rModOpts = getRModuleOptions(attribute, issueType,
1200:                            activeOnly);
1201:                    if (rModOpts != null) {
1202:
1203:                        // put options in a map for searching
1204:                        Map optionsMap = new HashMap(
1205:                                (int) (rModOpts.size() * 1.5));
1206:                        for (int i = rModOpts.size() - 1; i >= 0; i--) {
1207:                            RModuleOption rmo = (RModuleOption) rModOpts.get(i);
1208:                            optionsMap.put(rmo.getOptionId(), null);
1209:                        }
1210:
1211:                        // remove options with descendants in the list
1212:                        for (int i = rModOpts.size() - 1; i >= 0; i--) {
1213:                            AttributeOption option = ((RModuleOption) rModOpts
1214:                                    .get(i)).getAttributeOption();
1215:                            List descendants = option.getChildren();
1216:                            if (descendants != null) {
1217:                                for (int j = descendants.size() - 1; j >= 0; j--) {
1218:                                    AttributeOption descendant = (AttributeOption) descendants
1219:                                            .get(j);
1220:                                    if (optionsMap.containsKey(descendant
1221:                                            .getOptionId())) {
1222:                                        rModOpts.remove(i);
1223:                                        break;
1224:                                    }
1225:                                }
1226:                            }
1227:                        }
1228:                        getMethodResult().put(rModOpts, this ,
1229:                                GET_LEAF_R_MODULE_OPTIONS, attribute,
1230:                                issueType, activeBool);
1231:                    }
1232:                } else {
1233:                    rModOpts = (List) obj;
1234:                }
1235:
1236:                return rModOpts;
1237:            }
1238:
1239:            /**
1240:             * Gets a list of active RModuleOptions which have had their level
1241:             * within the options for this module set.
1242:             *
1243:             * @param attribute an <code>Attribute</code> value
1244:             * @return a <code>List</code> value
1245:             * @exception TorqueException if an error occurs
1246:             */
1247:            public List getOptionTree(Attribute attribute, IssueType issueType)
1248:                    throws TorqueException {
1249:                return getOptionTree(attribute, issueType, true);
1250:            }
1251:
1252:            /**
1253:             * Gets a list of RModuleOptions which have had their level
1254:             * within the options for this module set.
1255:             *
1256:             * @param attribute an <code>Attribute</code> value
1257:             * @param activeOnly a <code>boolean</code> value
1258:             * @return a <code>List</code> value
1259:             * @exception TorqueException if an error occurs
1260:             */
1261:            public List getOptionTree(Attribute attribute, IssueType issueType,
1262:                    boolean activeOnly) throws TorqueException {
1263:                // I think this code should place an option that had multiple parents -
1264:                // OSX and Mac,BSD is usual example - into the list in multiple places
1265:                // and it should have the level set differently for the two locations.
1266:                // The code is currently only placing the option in the list once.
1267:                // Since the behavior is not well spec'ed, leaving as it is. - jdm
1268:
1269:                List moduleOptions = null;
1270:                moduleOptions = getRModuleOptions(attribute, issueType,
1271:                        activeOnly);
1272:                if (moduleOptions == null) {
1273:                    return moduleOptions;
1274:                }
1275:
1276:                int size = moduleOptions.size();
1277:                List[] ancestors = new List[size];
1278:
1279:                // find all ancestors
1280:                for (int i = size - 1; i >= 0; i--) {
1281:                    AttributeOption option = ((RModuleOption) moduleOptions
1282:                            .get(i)).getAttributeOption();
1283:                    ancestors[i] = option.getAncestors();
1284:                }
1285:
1286:                for (int i = 0; i < size; i++) {
1287:                    RModuleOption moduleOption = (RModuleOption) moduleOptions
1288:                            .get(i);
1289:                    int level = 1;
1290:                    if (ancestors[i] != null) {
1291:                        // Set level for first ancestor as the option is only
1292:                        // shown once. 
1293:                        for (int j = ancestors[i].size() - 1; j >= 0; j--) {
1294:                            AttributeOption ancestor = (AttributeOption) ancestors[i]
1295:                                    .get(j);
1296:
1297:                            for (int k = 0; k < i; k++) {
1298:                                RModuleOption potentialParent = (RModuleOption) moduleOptions
1299:                                        .get(k);
1300:                                if (ancestor.getOptionId().equals(
1301:                                        potentialParent.getOptionId())
1302:                                        && !ancestor.getOptionId().equals(
1303:                                                moduleOption.getOptionId())) {
1304:                                    moduleOption.setLevel(level++);
1305:                                }
1306:                            }
1307:                        }
1308:                    }
1309:                }
1310:
1311:                return moduleOptions;
1312:            }
1313:
1314:            /** 
1315:             * This method is implemented in ScarabModule
1316:             */
1317:            public abstract List getRModuleIssueTypes() throws TorqueException;
1318:
1319:            public List getRModuleIssueTypes(String sortColumn,
1320:                    String sortPolarity) throws TorqueException {
1321:                List types = null;
1322:                Object obj = ScarabCache.get(this , GET_R_MODULE_ISSUE_TYPES);
1323:                if (obj == null) {
1324:                    Criteria crit = new Criteria();
1325:                    crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId())
1326:                            .addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
1327:                                    IssueTypePeer.ISSUE_TYPE_ID).add(
1328:                                    IssueTypePeer.PARENT_ID, 0).add(
1329:                                    IssueTypePeer.DELETED, 0);
1330:                    if (sortColumn.equals("name")) {
1331:                        if (sortPolarity.equals("desc")) {
1332:                            crit.addDescendingOrderByColumn(IssueTypePeer.NAME);
1333:                        } else {
1334:                            crit.addAscendingOrderByColumn(IssueTypePeer.NAME);
1335:                        }
1336:                    } else {
1337:                        // sortColumn defaults to sequence #
1338:                        if (sortPolarity.equals("desc")) {
1339:                            crit
1340:                                    .addDescendingOrderByColumn(RModuleIssueTypePeer.PREFERRED_ORDER);
1341:                        } else {
1342:                            crit
1343:                                    .addAscendingOrderByColumn(RModuleIssueTypePeer.PREFERRED_ORDER);
1344:                        }
1345:                    }
1346:                    types = RModuleIssueTypePeer.doSelect(crit);
1347:                    ScarabCache.put(types, this , GET_R_MODULE_ISSUE_TYPES);
1348:                } else {
1349:                    types = (List) obj;
1350:                }
1351:                return types;
1352:            }
1353:
1354:            /**
1355:             * Adds attribute options to a module.
1356:             */
1357:            public void addAttributeOption(final IssueType issueType,
1358:                    final AttributeOption option) throws TorqueException,
1359:                    ScarabException {
1360:                final RModuleOption rmo = addRModuleOption(issueType, option);
1361:                rmo.save();
1362:                shiftAttributeOption(option.getAttribute(), issueType, rmo
1363:                        .getOrder());
1364:
1365:                // add module-attributeoption mappings to template type
1366:                final IssueType templateType = IssueTypeManager
1367:                        .getInstance(issueType.getTemplateId());
1368:                final RModuleOption rmo2 = addRModuleOption(templateType,
1369:                        option);
1370:                rmo2.save();
1371:                //FIXME: is it useful to shift options for the templateType?
1372:                //shiftAttributeOption(option.getAttribute(), templateType, rmo.getOrder());
1373:
1374:                //if the cache is not cleared, when two options are added at the same time, 
1375:                //getLastAttributeOption does not take into account the newest active options.
1376:                ScarabCache.clear();
1377:            }
1378:
1379:            public void setRmaBasedOnIssueType(final RIssueTypeAttribute ria)
1380:                    throws TorqueException, ScarabException {
1381:                final RModuleAttribute rma = new RModuleAttribute();
1382:                rma.setModuleId(getModuleId());
1383:                rma.setIssueTypeId(ria.getIssueTypeId());
1384:                rma.setAttributeId(ria.getAttributeId());
1385:                rma.setActive(ria.getActive());
1386:                rma.setRequired(ria.getRequired());
1387:                rma.setOrder(ria.getOrder());
1388:                rma.setQuickSearch(ria.getQuickSearch());
1389:                rma.setDefaultTextFlag(ria.getDefaultTextFlag());
1390:                rma.save();
1391:                final RModuleAttribute rma2 = rma.copy();
1392:                rma2.setModuleId(getModuleId());
1393:                rma2.setIssueTypeId(ria.getIssueType().getTemplateId());
1394:                rma2.setAttributeId(ria.getAttributeId());
1395:                rma2.setActive(ria.getActive());
1396:                rma2.setRequired(ria.getRequired());
1397:                rma2.setOrder(ria.getOrder());
1398:                rma2.setQuickSearch(ria.getQuickSearch());
1399:                rma2.setDefaultTextFlag(ria.getDefaultTextFlag());
1400:                rma2.save();
1401:            }
1402:
1403:            public void setRmoBasedOnIssueType(final RIssueTypeOption rio)
1404:                    throws TorqueException, ScarabException {
1405:                final RModuleOption rmo = new RModuleOption();
1406:                rmo.setModuleId(getModuleId());
1407:                rmo.setIssueTypeId(rio.getIssueTypeId());
1408:                rmo.setOptionId(rio.getOptionId());
1409:                rmo.setActive(rio.getActive());
1410:                rmo.setOrder(rio.getOrder());
1411:                rmo.setWeight(rio.getWeight());
1412:                rmo.save();
1413:                final RModuleOption rmo2 = rmo.copy();
1414:                rmo2.setModuleId(getModuleId());
1415:                rmo2.setIssueTypeId(rio.getIssueType().getTemplateId());
1416:                rmo2.setOptionId(rio.getOptionId());
1417:                rmo2.setActive(rio.getActive());
1418:                rmo2.setOrder(rio.getOrder());
1419:                rmo2.setWeight(rio.getWeight());
1420:                rmo2.save();
1421:            }
1422:
1423:            protected String getValidationMessage(String typeName, String detail) {
1424:                final L10NMessage msg = new L10NMessage(VALIDATION_MESSAGE,
1425:                        typeName, getName(), detail);
1426:                return msg.getMessage();
1427:            }
1428:
1429:            public boolean includesIssueType(final IssueType issueType)
1430:                    throws TorqueException, DataSetException {
1431:                final Criteria crit = new Criteria();
1432:                crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId());
1433:                crit.add(RModuleIssueTypePeer.ISSUE_TYPE_ID, issueType
1434:                        .getIssueTypeId());
1435:                return RModuleIssueTypePeer.count(crit) > 0;
1436:            }
1437:
1438:            /**
1439:             * Adds an issue type to a module
1440:             * Copies properties from the global issue type's settings
1441:             */
1442:            public void addIssueType(final IssueType issueType)
1443:                    throws TorqueException, ValidationException,
1444:                    DataSetException, ScarabException {
1445:                // do some validation, refuse to add an issue type that is in a bad
1446:                // state
1447:                if (issueType == null) {
1448:                    throw new ValidationException(
1449:                            L10NKeySet.ExceptionIntegrityCheckFailure, "NULL",
1450:                            getName(), "Issue type was null");
1451:                }
1452:
1453:                // check that the issueType is not already added.
1454:                if (includesIssueType(issueType)) {
1455:                    throw new ValidationException(
1456:                            L10NKeySet.ExceptionDuplicateIssueType, issueType,
1457:                            getName());
1458:                }
1459:
1460:                final String typeName = issueType.getName();
1461:                // check attribute groups
1462:                final List testGroups = issueType.getAttributeGroups(null,
1463:                        false);
1464:                try {
1465:                    if (testGroups == null) {
1466:                        final Localizable l10nMessage = new L10NMessage(
1467:                                L10NKeySet.IssueTypeWasNull);
1468:                        throw new ValidationException(
1469:                                L10NKeySet.ExceptionIntegrityCheckFailure,
1470:                                typeName, getName(), l10nMessage);
1471:                    } else {
1472:                        for (Iterator i = testGroups.iterator(); i.hasNext();) {
1473:                            final AttributeGroup group = (AttributeGroup) i
1474:                                    .next();
1475:                            // check attributes
1476:                            final List attrs = group.getAttributes();
1477:                            if (attrs != null) {
1478:                                for (Iterator j = attrs.iterator(); j.hasNext();) {
1479:                                    // check attribute-attribute group maps
1480:                                    final Attribute attr = (Attribute) j.next();
1481:                                    if (attr == null) {
1482:                                        final L10NMessage l10nMessage = new L10NMessage(
1483:                                                L10NKeySet.AttributesContainsNull);
1484:                                        throw new ValidationException(
1485:                                                L10NKeySet.ExceptionIntegrityCheckFailure,
1486:                                                typeName, getName(),
1487:                                                l10nMessage);
1488:                                    }
1489:
1490:                                    // TODO: add workflow validation
1491:
1492:                                    final RAttributeAttributeGroup raag = group
1493:                                            .getRAttributeAttributeGroup(attr);
1494:                                    if (raag == null) {
1495:                                        final L10NMessage l10nMessage = new L10NMessage(
1496:                                                L10NKeySet.AttributeMappingIsMissing,
1497:                                                attr.getName());
1498:                                        throw new ValidationException(
1499:                                                L10NKeySet.ExceptionIntegrityCheckFailure,
1500:                                                typeName, getName(),
1501:                                                l10nMessage);
1502:
1503:                                    }
1504:
1505:                                    // check attribute-issue type maps
1506:                                    final RIssueTypeAttribute ria = issueType
1507:                                            .getRIssueTypeAttribute(attr);
1508:                                    if (ria == null) {
1509:                                        final L10NMessage l10nMessage = new L10NMessage(
1510:                                                L10NKeySet.AttributeToIssueTypeMappingIsMissing,
1511:                                                attr.getName());
1512:                                        throw new ValidationException(
1513:                                                L10NKeySet.ExceptionIntegrityCheckFailure,
1514:                                                typeName, getName(),
1515:                                                l10nMessage);
1516:                                    }
1517:
1518:                                    // check options
1519:                                    final List rios = issueType
1520:                                            .getRIssueTypeOptions(attr, false);
1521:                                    if (rios != null) {
1522:                                        for (Iterator k = rios.iterator(); k
1523:                                                .hasNext();) {
1524:                                            if (k.next() == null) {
1525:                                                final L10NMessage l10nMessage = new L10NMessage(
1526:                                                        L10NKeySet.ListOfOptionsMissing,
1527:                                                        attr.getName());
1528:                                                throw new ValidationException(
1529:                                                        L10NKeySet.ExceptionIntegrityCheckFailure,
1530:                                                        typeName, getName(),
1531:                                                        l10nMessage);
1532:                                            }
1533:                                        }
1534:                                    }
1535:                                }
1536:                            }
1537:                        }
1538:                    }
1539:                } catch (ValidationException ve) {
1540:                    throw ve;
1541:                } catch (Exception e) {
1542:                    throw new ScarabException(L10NKeySet.ExceptionGeneral, e
1543:                            .getMessage(), e);
1544:                }
1545:
1546:                // okay we passed, start modifying tables
1547:
1548:                // add module-issue type mapping
1549:                final RModuleIssueType rmit = new RModuleIssueType();
1550:                rmit.setModuleId(getModuleId());
1551:                rmit.setIssueTypeId(issueType.getIssueTypeId());
1552:                rmit.setActive(true);
1553:                rmit.setDisplay(false);
1554:                rmit.setOrder(getRModuleIssueTypes().size() + 1);
1555:                rmit.setDedupe(issueType.getDedupe());
1556:                rmit.save();
1557:
1558:                // add user attributes
1559:                final List userRIAs = issueType.getRIssueTypeAttributes(false,
1560:                        "user");
1561:                for (int m = 0; m < userRIAs.size(); m++) {
1562:                    final RIssueTypeAttribute userRia = (RIssueTypeAttribute) userRIAs
1563:                            .get(m);
1564:                    setRmaBasedOnIssueType(userRia);
1565:                }
1566:
1567:                // add workflow 
1568:                WorkflowFactory.getInstance().addIssueTypeWorkflowToModule(
1569:                        this , issueType);
1570:
1571:                // add attribute groups
1572:                final List groups = issueType.getAttributeGroups(null, false);
1573:                if (groups.isEmpty()) {
1574:                    // Create default groups
1575:                    final AttributeGroup ag = createNewGroup(issueType);
1576:                    ag.setOrder(1);
1577:                    ag.setDedupe(true);
1578:                    ag.setDescription(null);
1579:                    ag.save();
1580:                    final AttributeGroup ag2 = createNewGroup(issueType);
1581:                    ag2.setOrder(3);
1582:                    ag2.setDedupe(false);
1583:                    ag2.setDescription(null);
1584:                    ag2.save();
1585:                } else {
1586:                    // Inherit attribute groups from issue type
1587:                    for (int i = 0; i < groups.size(); i++) {
1588:                        final AttributeGroup group = (AttributeGroup) groups
1589:                                .get(i);
1590:                        final AttributeGroup moduleGroup = group.copyGroup();
1591:                        moduleGroup.setModuleId(getModuleId());
1592:                        moduleGroup.setIssueTypeId(issueType.getIssueTypeId());
1593:                        moduleGroup.save();
1594:
1595:                        // add attributes
1596:                        final List attrs = group.getAttributes();
1597:                        if (attrs != null) {
1598:                            for (int j = 0; j < attrs.size(); j++) {
1599:                                // save attribute-attribute group maps
1600:                                final Attribute attr = (Attribute) attrs.get(j);
1601:                                final RAttributeAttributeGroup raag = group
1602:                                        .getRAttributeAttributeGroup(attr);
1603:                                final RAttributeAttributeGroup moduleRaag = new RAttributeAttributeGroup();
1604:                                moduleRaag
1605:                                        .setAttributeId(raag.getAttributeId());
1606:                                moduleRaag.setOrder(raag.getOrder());
1607:                                moduleRaag.setGroupId(moduleGroup
1608:                                        .getAttributeGroupId());
1609:                                moduleRaag.save();
1610:
1611:                                // save attribute-module maps
1612:                                final RIssueTypeAttribute ria = issueType
1613:                                        .getRIssueTypeAttribute(attr);
1614:                                setRmaBasedOnIssueType(ria);
1615:
1616:                                // save options
1617:                                final List rios = issueType
1618:                                        .getRIssueTypeOptions(attr, false);
1619:                                if (rios != null) {
1620:                                    for (int k = 0; k < rios.size(); k++) {
1621:                                        final RIssueTypeOption rio = (RIssueTypeOption) rios
1622:                                                .get(k);
1623:                                        setRmoBasedOnIssueType(rio);
1624:                                    }
1625:                                }
1626:                            }
1627:                        }
1628:                    }
1629:                }
1630:            }
1631:
1632:            public RModuleIssueType getRModuleIssueType(
1633:                    final IssueType issueType) throws TorqueException {
1634:                RModuleIssueType rmit = null;
1635:                try {
1636:                    final SimpleKey[] keys = { SimpleKey.keyFor(getModuleId()),
1637:                            SimpleKey.keyFor(issueType.getIssueTypeId()) };
1638:                    rmit = RModuleIssueTypeManager.getInstance(new ComboKey(
1639:                            keys));
1640:                } catch (NoRowsException e) {
1641:                    // ignore and return null, if the rmit does not exist
1642:                }
1643:                return rmit;
1644:            }
1645:
1646:            public List getTemplateTypes() throws TorqueException,
1647:                    ScarabException {
1648:                List templateTypes = new ArrayList();
1649:                final Object obj = ScarabCache.get(this , GET_TEMPLATE_TYPES);
1650:                if (obj == null) {
1651:                    final Criteria crit = new Criteria();
1652:                    crit.add(RModuleIssueTypePeer.MODULE_ID, getModuleId())
1653:                            .addJoin(RModuleIssueTypePeer.ISSUE_TYPE_ID,
1654:                                    IssueTypePeer.ISSUE_TYPE_ID).add(
1655:                                    IssueTypePeer.DELETED, 0);
1656:                    final List rmits = RModuleIssueTypePeer.doSelect(crit);
1657:                    for (int i = 0; i < rmits.size(); i++) {
1658:                        final RModuleIssueType rmit = (RModuleIssueType) rmits
1659:                                .get(i);
1660:                        final IssueType templateType = rmit.getIssueType()
1661:                                .getTemplateIssueType();
1662:                        templateTypes.add(templateType);
1663:                    }
1664:                    ScarabCache.put(templateTypes, this , GET_TEMPLATE_TYPES);
1665:                } else {
1666:                    templateTypes = (List) obj;
1667:                }
1668:                return templateTypes;
1669:            }
1670:
1671:            /**
1672:             * Determines whether this module allows users to vote many times for
1673:             * the same issue.  This feature needs schema change to allow a
1674:             * configuration screen.  Currently only one vote per issue is supported
1675:             *
1676:             * @return false
1677:             */
1678:            public boolean allowsMultipleVoting() {
1679:                return false;
1680:            }
1681:
1682:            /**
1683:             * How many votes does the user have left to cast.  Currently always
1684:             * returns 1, so a user has unlimited voting rights.  Should look to
1685:             * UserVote for the answer when implemented properly.
1686:             */
1687:            public int getUnusedVoteCount(ScarabUser user) {
1688:                return 1;
1689:            }
1690:
1691:            /**
1692:             * Returns list of queries needing approval.
1693:             */
1694:            public List getUnapprovedQueries() throws TorqueException {
1695:                List queries = null;
1696:                Object obj = ScarabCache.get(this , GET_UNAPPROVED_QUERIES);
1697:                if (obj == null) {
1698:                    Criteria crit = new Criteria(3);
1699:                    crit.add(QueryPeer.APPROVED, 0).add(QueryPeer.DELETED, 0)
1700:                            .add(QueryPeer.MODULE_ID, getModuleId());
1701:                    queries = QueryPeer.doSelect(crit);
1702:                    ScarabCache.put(queries, this , GET_UNAPPROVED_QUERIES);
1703:                } else {
1704:                    queries = (List) obj;
1705:                }
1706:                return queries;
1707:            }
1708:
1709:            /**
1710:             * Returns list of enter issue templates needing approval.
1711:             */
1712:            public List getUnapprovedTemplates() throws TorqueException {
1713:                List templates = null;
1714:                Object obj = ScarabCache.get(this , GET_UNAPPROVED_TEMPLATES);
1715:                if (obj == null) {
1716:                    Criteria crit = new Criteria(3);
1717:                    crit.add(IssueTemplateInfoPeer.APPROVED, 0).addJoin(
1718:                            IssuePeer.ISSUE_ID, IssueTemplateInfoPeer.ISSUE_ID)
1719:                            .add(IssuePeer.DELETED, 0).add(IssuePeer.MOVED, 0)
1720:                            .add(IssuePeer.MODULE_ID, getModuleId());
1721:                    templates = IssuePeer.doSelect(crit);
1722:                    ScarabCache.put(templates, this , GET_UNAPPROVED_TEMPLATES);
1723:                } else {
1724:                    templates = (List) obj;
1725:                }
1726:                return templates;
1727:            }
1728:
1729:            /**
1730:             * for a new module: inherit issue types from parent module and 
1731:             * from the issue types marked as default
1732:             * parent configuration takes precedence over default
1733:             */
1734:            protected void setInitialAttributesAndIssueTypes()
1735:                    throws TorqueException, DataSetException, ScarabException {
1736:                isInitializing = true;
1737:                ValidationException ve = null;
1738:                try {
1739:                    // Add defaults for issue types and attributes 
1740:                    // from parent module
1741:                    final Module parentModule = ModuleManager
1742:                            .getInstance(getParentId());
1743:                    inheritFromParent(parentModule);
1744:
1745:                    final List defaultIssueTypes = IssueTypePeer
1746:                            .getDefaultIssueTypes();
1747:                    for (int i = 0; i < defaultIssueTypes.size(); i++) {
1748:                        final IssueType defaultIssueType = (IssueType) defaultIssueTypes
1749:                                .get(i);
1750:                        if (!includesIssueType(defaultIssueType)) {
1751:                            try {
1752:                                addIssueType(defaultIssueType);
1753:                            } catch (ValidationException e) {
1754:                                // if one issue type is bad, continue with the rest, if 
1755:                                // more than one bad issue type is found, stop.
1756:                                if (ve == null) {
1757:                                    ve = e;
1758:                                } else {
1759:                                    ve = new ValidationException(
1760:                                            L10NKeySet.ExceptionMultipleProblems,
1761:                                            ve.getMessage(), e);//WORK: what about the stack trace ?
1762:                                    isInitializing = false;
1763:                                    throw ve;
1764:                                }
1765:                            }
1766:                        }
1767:                    }
1768:                } finally {
1769:                    isInitializing = false;
1770:                }
1771:                if (ve != null) {
1772:                    throw ve;
1773:                }
1774:            }
1775:
1776:            /**
1777:             * sets up attributes and issue types for this module based on.
1778:             * the parent module
1779:             */
1780:            protected void inheritFromParent(final Module parentModule)
1781:                    throws TorqueException, ScarabException {
1782:                final Integer newModuleId = getModuleId();
1783:                AttributeGroup ag1;
1784:                AttributeGroup ag2;
1785:                RModuleAttribute rma1 = null;
1786:                RModuleAttribute rma2 = null;
1787:
1788:                //save RModuleAttributes for template types.
1789:                final List templateTypes = parentModule.getTemplateTypes();
1790:                for (int i = 0; i < templateTypes.size(); i++) {
1791:                    final IssueType it = (IssueType) templateTypes.get(i);
1792:                    final List rmas = parentModule.getRModuleAttributes(it);
1793:                    for (int j = 0; j < rmas.size(); j++) {
1794:                        rma1 = (RModuleAttribute) rmas.get(j);
1795:                        rma2 = rma1.copy();
1796:                        rma2.setModuleId(newModuleId);
1797:                        rma2.setAttributeId(rma1.getAttributeId());
1798:                        rma2.setIssueTypeId(rma1.getIssueTypeId());
1799:                        getLog().debug(
1800:                                "[ASM] Saving rma for new template type: "
1801:                                        + rma2.getModuleId() + "-"
1802:                                        + rma2.getIssueTypeId() + "-"
1803:                                        + rma2.getAttributeId());
1804:                        rma2.save();
1805:                    }
1806:                }
1807:
1808:                // set module-issue type mappings
1809:                final List rmits = parentModule.getRModuleIssueTypes();
1810:                for (int i = 0; i < rmits.size(); i++) {
1811:                    final RModuleIssueType rmit1 = (RModuleIssueType) rmits
1812:                            .get(i);
1813:                    final RModuleIssueType rmit2 = rmit1.copy();
1814:                    rmit2.setModuleId(newModuleId);
1815:                    rmit2.save();
1816:                    final IssueType issueType = rmit1.getIssueType();
1817:
1818:                    // set attribute group defaults
1819:                    final List attributeGroups = issueType.getAttributeGroups(
1820:                            parentModule, true);
1821:                    for (int j = 0; j < attributeGroups.size(); j++) {
1822:                        ag1 = (AttributeGroup) attributeGroups.get(j);
1823:                        ag2 = ag1.copy();
1824:                        ag2.setModuleId(newModuleId);
1825:                        ag2.getRAttributeAttributeGroups().clear(); // are saved later
1826:                        ag2.save();
1827:
1828:                        final List attributes = ag1.getAttributes();
1829:                        for (int k = 0; k < attributes.size(); k++) {
1830:                            final Attribute attribute = (Attribute) attributes
1831:                                    .get(k);
1832:
1833:                            // set attribute-attribute group defaults
1834:                            final RAttributeAttributeGroup raag1 = ag1
1835:                                    .getRAttributeAttributeGroup(attribute);
1836:                            final RAttributeAttributeGroup raag2 = raag1.copy();
1837:                            raag2.setGroupId(ag2.getAttributeGroupId());
1838:                            raag2.setAttributeId(raag1.getAttributeId());
1839:                            raag2.setOrder(raag1.getOrder());
1840:                            raag2.save();
1841:                        }
1842:                    }
1843:
1844:                    // set module-attribute defaults
1845:                    final List rmas = parentModule
1846:                            .getRModuleAttributes(issueType);
1847:                    if (rmas != null && rmas.size() > 0) {
1848:                        for (int j = 0; j < rmas.size(); j++) {
1849:                            rma1 = (RModuleAttribute) rmas.get(j);
1850:                            rma2 = rma1.copy();
1851:                            rma2.setModuleId(newModuleId);
1852:                            rma2.setAttributeId(rma1.getAttributeId());
1853:                            rma2.setIssueTypeId(rma1.getIssueTypeId());
1854:                            rma2.save();
1855:
1856:                            // set module-option mappings
1857:                            final Attribute attribute = rma1.getAttribute();
1858:                            if (attribute.isOptionAttribute()) {
1859:                                final List rmos = parentModule
1860:                                        .getRModuleOptions(attribute, issueType);
1861:                                if (rmos != null && rmos.size() > 0) {
1862:                                    for (int m = 0; m < rmos.size(); m++) {
1863:                                        final RModuleOption rmo1 = (RModuleOption) rmos
1864:                                                .get(m);
1865:                                        final RModuleOption rmo2 = rmo1.copy();
1866:                                        rmo2.setOptionId(rmo1.getOptionId());
1867:                                        rmo2.setModuleId(newModuleId);
1868:                                        rmo2.setIssueTypeId(issueType
1869:                                                .getIssueTypeId());
1870:                                        rmo2.save();
1871:
1872:                                        // Save module-option mappings for template types
1873:                                        final RModuleOption rmo3 = rmo1.copy();
1874:                                        rmo3.setOptionId(rmo1.getOptionId());
1875:                                        rmo3.setModuleId(newModuleId);
1876:                                        rmo3.setIssueTypeId(issueType
1877:                                                .getTemplateId());
1878:                                        rmo3.save();
1879:                                    }
1880:                                }
1881:                            }
1882:                        }
1883:                    }
1884:                }
1885:            }
1886:
1887:            /**
1888:             * Determines whether this module is accepting new issues.  This default
1889:             * implementation allows new issues if the module has not been deleted.
1890:             */
1891:            public boolean allowsNewIssues() {
1892:                return !getDeleted();
1893:            }
1894:
1895:            /**
1896:             * Determines whether this module accepts issues.  This default
1897:             * implementation does allow issues.
1898:             */
1899:            public boolean allowsIssues() {
1900:                return true;
1901:            }
1902:
1903:            /**
1904:             * Returns true if no issue types are associated with this module, or if the module
1905:             * is currently getting its initial values set.
1906:             */
1907:            public boolean isInitializing() throws TorqueException {
1908:                return isInitializing;
1909:            }
1910:
1911:            /**
1912:             * @see org.tigris.scarab.om.Module#isGlobalModule()
1913:             */
1914:            public boolean isGlobalModule() {
1915:                return Module.ROOT_ID.equals(getModuleId());
1916:            }
1917:
1918:            // FIXME! should localize
1919:            private static final String REGEX_PREFIX = "([:alpha:]+\\d+)|(issue|bug|artifact";
1920:            private static final String REGEX_SUFFIX = ")\\s*#?([:alpha:]*\\d+)";
1921:
1922:            public String getIssueRegexString() throws TorqueException {
1923:                // regex =  /(issue|bug)\s+#?\d+/i
1924:                List rmitsList = getRModuleIssueTypes();
1925:                StringBuffer regex = new StringBuffer(30 + 10 * rmitsList
1926:                        .size());
1927:                regex.append(REGEX_PREFIX);
1928:                Iterator rmits = rmitsList.iterator();
1929:                while (rmits.hasNext()) {
1930:                    regex.append('|').append(
1931:                            ((RModuleIssueType) rmits.next()).getDisplayName());
1932:                }
1933:                regex.append(REGEX_SUFFIX);
1934:                return regex.toString();
1935:            }
1936:
1937:            /**
1938:             * @see org.tigris.scarab.om.Module#getIssueRegex()
1939:             */
1940:            public REProgram getIssueRegex() throws TorqueException {
1941:                String regex = getIssueRegexString();
1942:                RECompiler rec = new RECompiler();
1943:                REProgram rep = null;
1944:                try {
1945:                    rep = rec.compile(regex);
1946:                } catch (RESyntaxException e) {
1947:                    getLog().error("Could not compile regex: " + regex, e);
1948:                    try {
1949:                        rep = rec.compile(REGEX_PREFIX + REGEX_SUFFIX);
1950:                    } catch (RESyntaxException ee) {
1951:                        // this should not happen, but it might when we localize
1952:                        getLog().error("Could not compile standard regex", ee);
1953:                        try {
1954:                            rep = rec.compile("[:alpha:]+\\d+");
1955:                        } catch (RESyntaxException eee) {
1956:                            // this will never happen, but log it, just in case 
1957:                            getLog().error("Could not compile simple id regex",
1958:                                    eee);
1959:                        }
1960:                    }
1961:                }
1962:                // FIXME: we should cache the above result
1963:                return rep;
1964:            }
1965:
1966:            /**
1967:             * All emails related to this module will have a copy sent to
1968:             * this address.  A system-wide default email address can be specified in 
1969:             * Scarab.properties with the key: scarab.email.archive.toAddress
1970:             */
1971:            public abstract String getArchiveEmail();
1972:
1973:            /**
1974:             * Simple implementation returns the single configured default locale
1975:             * from TR.props.  Will be replaced by a way to set this per module.
1976:             *
1977:             * @return a Locale selected for the Fulcrum Localization context
1978:             */
1979:            public Locale getLocale() {
1980:                return ScarabConstants.DEFAULT_LOCALE;
1981:            }
1982:
1983:            /**
1984:             * The default address that is used to fill out either the From or
1985:             * ReplyTo header on emails related to this module.  In many cases
1986:             * the From field is taken as the user who acted that resulted in the 
1987:             * email, but replies should still go to the central location for
1988:             * the module, so in this address would be used in the ReplyTo field.
1989:             *
1990:             * @return a <code>String[]</code> of length=2 where the first element
1991:             * is a name such as "Scarab System" and the second is an email address.
1992:             */
1993:            public String[] getSystemEmail() {
1994:                String name = Turbine.getConfiguration().getString(
1995:                        "scarab.email.default.fromName");
1996:                if (name == null || name.length() == 0) {
1997:                    name = Localization.format(
1998:                            ScarabConstants.DEFAULT_BUNDLE_NAME, getLocale(),
1999:                            "DefaultEmailNameForModule", getRealName()
2000:                                    .toUpperCase());
2001:                }
2002:
2003:                String email = Turbine.getConfiguration().getString(
2004:                        "scarab.email.default.fromAddress");
2005:
2006:                if (email == null || email.length() == 0) {
2007:                    email = getArchiveEmail();
2008:                }
2009:                if (email == null || email.length() == 0) {
2010:                    email = "help@localhost";
2011:                }
2012:                String[] result = { name, email };
2013:                return result;
2014:            }
2015:
2016:            /**
2017:             * Used for ordering Groups.
2018:             *
2019:             * @param obj The Object to compare to.
2020:             * @return -1 if the name of the other object is lexically greater than 
2021:             * this group, 1 if it is lexically lesser, 0 if they are equal.
2022:             */
2023:            public int compareTo(Object obj) {
2024:                //TODO [HD] what about using instanceof, or
2025:                //          probably better delete the whole
2026:                //          if-block (see note n ScarabModule.compereTo()
2027:                if (this .getClass() != obj.getClass()) {
2028:                    throw new ClassCastException(); //EXCEPTION 
2029:                }
2030:                String name1 = ((Group) obj).getName();
2031:                String name2 = this .getName();
2032:
2033:                return name2.compareTo(name1);
2034:            }
2035:
2036:            public String toString() {
2037:                String name = getName();
2038:                if (name == null) {
2039:                    name = getRealName();
2040:                }
2041:                if (name == null) {
2042:                    name = getClass().getName();
2043:                }
2044:                return name;
2045:            }
2046:
2047:            private MethodResultCache getMethodResult() {
2048:                return ModuleManager.getMethodResult();
2049:            }
2050:
2051:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.