Source Code Cross Referenced for IssueType.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:        import com.workingdogs.village.DataSetException;
0050:        import java.util.List;
0051:        import java.util.ArrayList;
0052:        import java.util.Iterator;
0053:        import java.util.Properties;
0054:        import java.io.InputStream;
0055:        import java.io.IOException;
0056:        import org.apache.torque.TorqueException;
0057:
0058:        import org.apache.torque.util.Criteria;
0059:        import org.apache.torque.om.Persistent;
0060:        import org.apache.torque.manager.MethodResultCache;
0061:        import org.apache.fulcrum.localization.Localization;
0062:
0063:        import org.tigris.scarab.services.cache.ScarabCache;
0064:        import org.tigris.scarab.tools.localization.L10NKeySet;
0065:        import org.tigris.scarab.om.Module;
0066:        import org.tigris.scarab.om.IssuePeer;
0067:        import org.tigris.scarab.util.ScarabException;
0068:        import org.tigris.scarab.util.ScarabConstants;
0069:        import org.tigris.scarab.util.Log;
0070:        import org.tigris.scarab.workflow.Workflow;
0071:        import org.tigris.scarab.workflow.WorkflowFactory;
0072:
0073:        /** 
0074:         * This class represents an IssueType.
0075:         *
0076:         * @author <a href="mailto:elicia@collab.net">Elicia David</a>
0077:         * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
0078:         * @version $Id: IssueType.java 10123 2006-05-30 09:46:01Z dabbous $
0079:         */
0080:        public class IssueType extends BaseIssueType implements  Persistent {
0081:            private static final String ISSUE_TYPE = "IssueType";
0082:            private static final String GET_TEMPLATE_ISSUE_TYPE = "getTemplateIssueType";
0083:            private static final String GET_INSTANCE = "getInstance";
0084:            protected static final String GET_ATTRIBUTE_GROUPS = "getAttributeGroups";
0085:            protected static final String GET_ATTRIBUTE_GROUP = "getAttributeGroup";
0086:            protected static final String GET_R_ISSUETYPE_ATTRIBUTES = "getRIssueTypeAttributes";
0087:            protected static final String GET_R_ISSUETYPE_OPTIONS = "getRIssueTypeOptions";
0088:            protected static final String GET_ALL_R_ISSUETYPE_OPTIONS = "getAllRIssueTypeOptions";
0089:            protected static final String GET_DEFAULT_TEXT_ATTRIBUTE = "getDefaultTextAttribute";
0090:            protected static final String GET_QUICK_SEARCH_ATTRIBUTES = "getQuickSearchAttributes";
0091:            protected static final String GET_REQUIRED_ATTRIBUTES = "getRequiredAttributes";
0092:            protected static final String GET_ACTIVE_ATTRIBUTES = "getActiveAttributes";
0093:
0094:            static final String USER = "user";
0095:            static final String NON_USER = "non-user";
0096:
0097:            private static final Properties SYSTEM_CONFIG = new Properties();
0098:
0099:            //loads the properties file that specifies system defined issue types
0100:            static {
0101:                InputStream in = IssueType.class
0102:                        .getResourceAsStream("IssueTypeConfig.properties");
0103:                if (in != null) {
0104:                    try {
0105:                        SYSTEM_CONFIG.load(in);
0106:                    } catch (IOException ioe) {
0107:                        Log
0108:                                .get()
0109:                                .warn(
0110:                                        "Exception while loading the file: IssueTypeConfig.properties",
0111:                                        ioe);
0112:                    }
0113:                }
0114:            }
0115:
0116:            // this will not change, so only look it up once.
0117:            private IssueType templateIssueType;
0118:
0119:            // this will not change, so only look it up once.
0120:            private IssueType parentIssueType;
0121:
0122:            /**
0123:             * Gets the IssueType template for this IssueType. The template
0124:             * is a special type of IssueType.
0125:             */
0126:            public IssueType getTemplateIssueType() throws TorqueException,
0127:                    ScarabException {
0128:                if (templateIssueType == null) {
0129:                    final Criteria crit = new Criteria();
0130:                    crit.add(IssueTypePeer.PARENT_ID, getIssueTypeId());
0131:                    final List results = IssueTypePeer.doSelect(crit);
0132:                    if (results.isEmpty()) {
0133:                        throw new ScarabException(
0134:                                L10NKeySet.ExceptionTemplateTypeForIssueType);
0135:                    } else {
0136:                        templateIssueType = (IssueType) results.get(0);
0137:                    }
0138:                }
0139:                return templateIssueType;
0140:            }
0141:
0142:            /**
0143:             * Gets the parent IssueType for this template IssueType. The template
0144:             * is a special type of IssueType.
0145:             */
0146:            public IssueType getIssueTypeForTemplateType()
0147:                    throws TorqueException {
0148:                if (parentIssueType == null) {
0149:                    parentIssueType = getIssueTypeRelatedByParentId();
0150:                }
0151:                return parentIssueType;
0152:            }
0153:
0154:            /**
0155:             * Gets the id of the template that corresponds to the issue type.
0156:             */
0157:            public Integer getTemplateId() throws TorqueException,
0158:                    ScarabException {
0159:                return getTemplateIssueType().getIssueTypeId();
0160:            }
0161:
0162:            /**
0163:             *  Returns true if the issue type has issues associated with it.
0164:             */
0165:            public boolean hasIssues() throws TorqueException, DataSetException {
0166:                return hasIssues((Module) null);
0167:            }
0168:
0169:            /**
0170:             * If module name is identical to global name, return the global 
0171:             * name. Otherwise return the module name followed by a space 
0172:             * and the global name in parentheses.
0173:             * @return a <code>String</code> representation of the display name.
0174:             */
0175:            public String getDisplayName(Module module) throws TorqueException {
0176:                String moduleName = module.getRModuleIssueType(this )
0177:                        .getDisplayName();
0178:                String displayName = getName();
0179:                if (!moduleName.equals(displayName)) {
0180:                    displayName = moduleName + " (" + displayName + ")";
0181:                }
0182:                return displayName;
0183:            }
0184:
0185:            /**
0186:             *  Returns true if the issue type/module has issues associated with it.
0187:             */
0188:            public boolean hasIssues(Module module) throws TorqueException,
0189:                    DataSetException {
0190:                Criteria crit = new Criteria();
0191:                crit.add(IssuePeer.TYPE_ID, getIssueTypeId());
0192:                if (module != null) {
0193:                    crit.add(IssuePeer.MODULE_ID, module.getModuleId());
0194:                }
0195:                return (IssuePeer.count(crit) > 0);
0196:            }
0197:
0198:            /**
0199:             * Get the IssueType using a issue type name
0200:             */
0201:            public static IssueType getInstance(final String issueTypeName)
0202:                    throws TorqueException, ScarabException {
0203:                IssueType result = null;
0204:                Object obj = ScarabCache.get(ISSUE_TYPE, GET_INSTANCE,
0205:                        issueTypeName);
0206:                if (obj == null) {
0207:                    final Criteria crit = new Criteria();
0208:                    crit.add(IssueTypePeer.NAME, issueTypeName);
0209:                    final List issueTypes = IssueTypePeer.doSelect(crit);
0210:                    if (issueTypes == null || issueTypes.size() == 0) {
0211:                        throw new ScarabException(
0212:                                L10NKeySet.ExceptionInvalidIssueType,
0213:                                issueTypeName);
0214:                    }
0215:                    result = (IssueType) issueTypes.get(0);
0216:                    ScarabCache.put(result, ISSUE_TYPE, GET_INSTANCE,
0217:                            issueTypeName);
0218:                } else {
0219:                    result = (IssueType) obj;
0220:                }
0221:                return result;
0222:            }
0223:
0224:            /**
0225:             * Copy the IssueType and its corresponding template type 
0226:             */
0227:            public IssueType copyIssueType() throws TorqueException,
0228:                    ScarabException {
0229:                final IssueType newIssueType = new IssueType();
0230:                newIssueType.setName(getName() + " (copy)");
0231:                newIssueType.setDescription(getDescription());
0232:                newIssueType.setParentId(ScarabConstants.INTEGER_0);
0233:                newIssueType.save();
0234:                final Integer newId = newIssueType.getIssueTypeId();
0235:
0236:                // Copy template type
0237:                final IssueType template = IssueTypePeer
0238:                        .retrieveByPK(getTemplateId());
0239:                final IssueType newTemplate = new IssueType();
0240:                newTemplate.setName(template.getName());
0241:                newTemplate.setParentId(newId);
0242:                newTemplate.save();
0243:
0244:                // Copy user attributes
0245:                final List userRIAs = getRIssueTypeAttributes(false, USER);
0246:                for (int m = 0; m < userRIAs.size(); m++) {
0247:                    final RIssueTypeAttribute userRia = (RIssueTypeAttribute) userRIAs
0248:                            .get(m);
0249:                    final RIssueTypeAttribute newUserRia = userRia.copyRia();
0250:                    newUserRia.setIssueTypeId(newId);
0251:                    newUserRia.save();
0252:                }
0253:
0254:                // Copy attribute groups
0255:                final List attrGroups = getAttributeGroups(false);
0256:                for (int i = 0; i < attrGroups.size(); i++) {
0257:                    final AttributeGroup group = (AttributeGroup) attrGroups
0258:                            .get(i);
0259:                    final AttributeGroup newGroup = group.copyGroup();
0260:                    newGroup.setIssueTypeId(newId);
0261:                    newGroup.save();
0262:
0263:                    // add attributes
0264:                    final List attrs = group.getAttributes();
0265:                    if (attrs != null) {
0266:                        for (int j = 0; j < attrs.size(); j++) {
0267:                            // save attribute-attribute group maps
0268:                            final Attribute attr = (Attribute) attrs.get(j);
0269:                            final RAttributeAttributeGroup raag = group
0270:                                    .getRAttributeAttributeGroup(attr);
0271:                            final RAttributeAttributeGroup newRaag = new RAttributeAttributeGroup();
0272:                            newRaag.setAttributeId(raag.getAttributeId());
0273:                            newRaag.setOrder(raag.getOrder());
0274:                            newRaag.setGroupId(newGroup.getAttributeGroupId());
0275:                            newRaag.save();
0276:
0277:                            // save attribute-issueType maps
0278:                            final RIssueTypeAttribute ria = getRIssueTypeAttribute(attr);
0279:                            final RIssueTypeAttribute newRia = ria.copyRia();
0280:                            newRia.setIssueTypeId(newId);
0281:                            newRia.save();
0282:
0283:                            // save options
0284:                            final List rios = getRIssueTypeOptions(attr, false);
0285:                            if (rios != null) {
0286:                                for (int k = 0; k < rios.size(); k++) {
0287:                                    final RIssueTypeOption rio = (RIssueTypeOption) rios
0288:                                            .get(k);
0289:                                    final RIssueTypeOption newRio = rio
0290:                                            .copyRio();
0291:                                    newRio.setIssueTypeId(newId);
0292:                                    newRio.save();
0293:                                }
0294:                            }
0295:                        }
0296:                    }
0297:                }
0298:
0299:                // add workflow 
0300:                WorkflowFactory.getInstance().copyIssueTypeWorkflows(this ,
0301:                        newIssueType);
0302:
0303:                return newIssueType;
0304:            }
0305:
0306:            /**
0307:             * Delete mappings with all modules
0308:             */
0309:            public void deleteModuleMappings(final ScarabUser user)
0310:                    throws TorqueException, ScarabException {
0311:                final Criteria crit = new Criteria();
0312:                crit.add(RModuleIssueTypePeer.ISSUE_TYPE_ID, getIssueTypeId());
0313:                final List rmits = RModuleIssueTypePeer.doSelect(crit);
0314:                for (int i = 0; i < rmits.size(); i++) {
0315:                    final RModuleIssueType rmit = (RModuleIssueType) rmits
0316:                            .get(i);
0317:                    rmit.delete(user);
0318:                }
0319:                ScarabCache.clear();
0320:            }
0321:
0322:            /**
0323:             * Create default groups upon issue type creation.
0324:             */
0325:            public void createDefaultGroups() throws TorqueException {
0326:                AttributeGroup ag = createNewGroup();
0327:                ag.setOrder(1);
0328:                ag.setDedupe(true);
0329:                ag.setDescription(null);
0330:                ag.save();
0331:                AttributeGroup ag2 = createNewGroup();
0332:                ag2.setOrder(3);
0333:                ag2.setDedupe(false);
0334:                ag2.setDescription(null);
0335:                ag2.save();
0336:            }
0337:
0338:            public List getAttributeGroups(Module module)
0339:                    throws TorqueException {
0340:                return getAttributeGroups(module, false);
0341:            }
0342:
0343:            public List getAttributeGroups(boolean activeOnly)
0344:                    throws TorqueException {
0345:                return getAttributeGroups(null, activeOnly);
0346:            }
0347:
0348:            /**
0349:             * List of attribute groups associated with this module).
0350:             */
0351:            public List getAttributeGroups(Module module, boolean activeOnly)
0352:                    throws TorqueException {
0353:                List groups = null;
0354:                Boolean activeBool = activeOnly ? Boolean.TRUE : Boolean.FALSE;
0355:                Object obj = getMethodResult().get(this , GET_ATTRIBUTE_GROUPS,
0356:                        module, activeBool);
0357:                if (obj == null) {
0358:                    Criteria crit = new Criteria().add(
0359:                            AttributeGroupPeer.ISSUE_TYPE_ID, getIssueTypeId())
0360:                            .addAscendingOrderByColumn(
0361:                                    AttributeGroupPeer.PREFERRED_ORDER);
0362:                    if (activeOnly) {
0363:                        crit.add(AttributeGroupPeer.ACTIVE, true);
0364:                    }
0365:                    if (module != null) {
0366:                        crit.add(AttributeGroupPeer.MODULE_ID, module
0367:                                .getModuleId());
0368:                    } else {
0369:                        // TODO Change this to be crit.add(AttributeGroupPeer.MODULE_ID, Criteria.ISNULL) when torque is fixed
0370:                        crit
0371:                                .add(
0372:                                        AttributeGroupPeer.MODULE_ID,
0373:                                        (Object) (AttributeGroupPeer.MODULE_ID + " IS NULL"),
0374:                                        Criteria.CUSTOM);
0375:                    }
0376:                    groups = AttributeGroupPeer.doSelect(crit);
0377:                    getMethodResult().put(groups, this , GET_ATTRIBUTE_GROUPS,
0378:                            module, activeBool);
0379:                } else {
0380:                    groups = (List) obj;
0381:                }
0382:                return groups;
0383:            }
0384:
0385:            public AttributeGroup createNewGroup() throws TorqueException {
0386:                return createNewGroup(null);
0387:            }
0388:
0389:            /**
0390:             * Creates new attribute group.
0391:             */
0392:            public AttributeGroup createNewGroup(Module module)
0393:                    throws TorqueException {
0394:                List groups = getAttributeGroups(module, false);
0395:                AttributeGroup ag = new AttributeGroup();
0396:
0397:                // Make default group name 'new attribute group' 
0398:                ag.setName(Localization.getString("ScarabBundle",
0399:                        ScarabConstants.DEFAULT_LOCALE, "NewAttributeGroup"));
0400:                ag.setActive(true);
0401:                ag.setIssueTypeId(getIssueTypeId());
0402:                if (module != null) {
0403:                    ag.setModuleId(module.getModuleId());
0404:                }
0405:                if (groups.size() == 0) {
0406:                    ag.setDedupe(true);
0407:                    ag.setOrder(groups.size() + 1);
0408:                } else {
0409:                    ag.setDedupe(false);
0410:                    ag.setOrder(groups.size() + 2);
0411:                }
0412:                ag.save();
0413:                groups.add(ag);
0414:                return ag;
0415:            }
0416:
0417:            /**
0418:             * Gets the sequence where the dedupe screen fits between groups.
0419:             *
0420:             * @see #getDedupeSequence(Module)
0421:             */
0422:            public int getDedupeSequence() throws TorqueException {
0423:                return getDedupeSequence(null);
0424:            }
0425:
0426:            /**
0427:             * Gets the sequence where the dedupe screen fits between groups.
0428:             *
0429:             * @param module A specific Module to retrieve AttributeGroup
0430:             * associations for, or <code>null</code> for groups associated
0431:             * with the global issue type.
0432:             */
0433:            int getDedupeSequence(Module module) throws TorqueException {
0434:                List groups = getAttributeGroups(module, false);
0435:                int sequence = groups.size() + 1;
0436:                for (int i = 1; i <= groups.size(); i++) {
0437:                    int order;
0438:                    int previousOrder;
0439:                    try {
0440:                        order = ((AttributeGroup) groups.get(i)).getOrder();
0441:                        previousOrder = ((AttributeGroup) groups.get(i - 1))
0442:                                .getOrder();
0443:                    } catch (Exception e) {
0444:                        Log.get().warn(
0445:                                "Error accessing dedupe sequence for issue "
0446:                                        + "type '" + this  + '\'', e);
0447:                        return sequence;
0448:                    }
0449:
0450:                    if (order != previousOrder + 1) {
0451:                        sequence = order - 1;
0452:                        break;
0453:                    }
0454:                }
0455:                return sequence;
0456:            }
0457:
0458:            /**
0459:             * Gets associated attributes.
0460:             */
0461:            public List getRIssueTypeAttributes() {
0462:                List rias = null;
0463:                try {
0464:                    rias = getRIssueTypeAttributes(false);
0465:                } catch (Exception e) {
0466:                    Log.get().warn(
0467:                            "Could not get RIA records for " + getName(), e);
0468:                }
0469:                return rias;
0470:            }
0471:
0472:            /**
0473:             * Gets associated attributes.
0474:             */
0475:            public List getRIssueTypeAttributes(boolean activeOnly)
0476:                    throws TorqueException {
0477:                return getRIssueTypeAttributes(activeOnly, "all");
0478:            }
0479:
0480:            /**
0481:             * Gets associated attributes.
0482:             */
0483:            public List getRIssueTypeAttributes(boolean activeOnly,
0484:                    String attributeType) throws TorqueException {
0485:                List rias = null;
0486:                Boolean activeBool = (activeOnly ? Boolean.TRUE : Boolean.FALSE);
0487:                Object obj = getMethodResult().get(this ,
0488:                        GET_R_ISSUETYPE_ATTRIBUTES, activeBool, attributeType);
0489:                if (obj == null) {
0490:                    Criteria crit = new Criteria();
0491:                    crit.add(RIssueTypeAttributePeer.ISSUE_TYPE_ID,
0492:                            getIssueTypeId());
0493:                    crit
0494:                            .addAscendingOrderByColumn(RIssueTypeAttributePeer.PREFERRED_ORDER);
0495:
0496:                    if (activeOnly) {
0497:                        crit.add(RIssueTypeAttributePeer.ACTIVE, true);
0498:                    }
0499:
0500:                    if (USER.equals(attributeType)) {
0501:                        crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
0502:                                AttributeTypePeer.USER_TYPE_KEY);
0503:                        crit.addJoin(AttributePeer.ATTRIBUTE_ID,
0504:                                RIssueTypeAttributePeer.ATTRIBUTE_ID);
0505:                    } else if (NON_USER.equals(attributeType)) {
0506:                        crit.addJoin(AttributePeer.ATTRIBUTE_ID,
0507:                                RIssueTypeAttributePeer.ATTRIBUTE_ID);
0508:                        crit.add(AttributePeer.ATTRIBUTE_TYPE_ID,
0509:                                AttributeTypePeer.USER_TYPE_KEY,
0510:                                Criteria.NOT_EQUAL);
0511:                    }
0512:
0513:                    rias = RIssueTypeAttributePeer.doSelect(crit);
0514:                    getMethodResult().put(rias, this ,
0515:                            GET_R_ISSUETYPE_ATTRIBUTES, activeBool,
0516:                            attributeType);
0517:                } else {
0518:                    rias = (List) obj;
0519:                }
0520:                return rias;
0521:            }
0522:
0523:            /**
0524:             * Gets associated activeattributes.
0525:             */
0526:            public List getAttributes(String attributeType)
0527:                    throws TorqueException {
0528:                ArrayList attrs = new ArrayList();
0529:                List rias = getRIssueTypeAttributes(true, attributeType);
0530:                for (int i = 0; i < rias.size(); i++) {
0531:                    attrs.add(((RIssueTypeAttribute) rias.get(i))
0532:                            .getAttribute());
0533:                }
0534:                return attrs;
0535:            }
0536:
0537:            /**
0538:             * Adds issuetype-attribute mapping to issue type.
0539:             */
0540:            public RIssueTypeAttribute addRIssueTypeAttribute(
0541:                    Attribute attribute) throws TorqueException {
0542:                String attributeType = null;
0543:                attributeType = (attribute.isUserAttribute() ? USER : NON_USER);
0544:
0545:                RIssueTypeAttribute ria = new RIssueTypeAttribute();
0546:                ria.setIssueTypeId(getIssueTypeId());
0547:                ria.setAttributeId(attribute.getAttributeId());
0548:                ria.setOrder(getLastAttribute(attributeType) + 1);
0549:                ria.save();
0550:                getRIssueTypeAttributes(false, attributeType).add(ria);
0551:                return ria;
0552:            }
0553:
0554:            public RIssueTypeAttribute getRIssueTypeAttribute(
0555:                    Attribute attribute) throws TorqueException {
0556:                RIssueTypeAttribute ria = null;
0557:                List rias = null;
0558:                if (attribute.isUserAttribute()) {
0559:                    rias = getRIssueTypeAttributes(false, USER);
0560:                } else {
0561:                    rias = getRIssueTypeAttributes(false, NON_USER);
0562:                }
0563:                Iterator i = rias.iterator();
0564:                while (i.hasNext()) {
0565:                    RIssueTypeAttribute tempRia = (RIssueTypeAttribute) i
0566:                            .next();
0567:                    if (tempRia.getAttribute().equals(attribute)) {
0568:                        ria = tempRia;
0569:                        break;
0570:                    }
0571:                }
0572:                return ria;
0573:            }
0574:
0575:            /**
0576:             * gets a list of all of the User Attributes in an issue type.
0577:             */
0578:            public List getUserAttributes() throws TorqueException {
0579:                return getUserAttributes(true);
0580:            }
0581:
0582:            /**
0583:             * gets a list of all of the User Attributes in an issue type.
0584:             */
0585:            public List getUserAttributes(boolean activeOnly)
0586:                    throws TorqueException {
0587:                List rIssueTypeAttributes = getRIssueTypeAttributes(activeOnly,
0588:                        USER);
0589:                List userAttributes = new ArrayList();
0590:
0591:                for (int i = 0; i < rIssueTypeAttributes.size(); i++) {
0592:                    Attribute att = ((RIssueTypeAttribute) rIssueTypeAttributes
0593:                            .get(i)).getAttribute();
0594:                    userAttributes.add(att);
0595:                }
0596:                return userAttributes;
0597:            }
0598:
0599:            /**
0600:             * FIXME: can this be done more efficently?
0601:             * gets highest sequence number for issueType-attribute map
0602:             * so that a new RIssueTypeAttribute can be added at the end.
0603:             */
0604:            public int getLastAttribute(String attributeType)
0605:                    throws TorqueException {
0606:                List itAttributes = getRIssueTypeAttributes(false,
0607:                        attributeType);
0608:                int last = 0;
0609:
0610:                for (int i = 0; i < itAttributes.size(); i++) {
0611:                    int order = ((RIssueTypeAttribute) itAttributes.get(i))
0612:                            .getOrder();
0613:                    if (order > last) {
0614:                        last = order;
0615:                    }
0616:                }
0617:                return last;
0618:            }
0619:
0620:            /**
0621:             * FIXME: can this be done more efficently?
0622:             * gets highest sequence number for module-attribute map
0623:             * so that a new RIssueTypeOption can be added at the end.
0624:             */
0625:            public int getLastAttributeOption(Attribute attribute)
0626:                    throws TorqueException {
0627:                List issueTypeOptions = getRIssueTypeOptions(attribute);
0628:                int last = 0;
0629:
0630:                for (int i = 0; i < issueTypeOptions.size(); i++) {
0631:                    int order = ((RIssueTypeOption) issueTypeOptions.get(i))
0632:                            .getOrder();
0633:                    if (order > last) {
0634:                        last = order;
0635:                    }
0636:                }
0637:                return last;
0638:            }
0639:
0640:            /**
0641:             * Adds issuetype-attribute-option mapping to module.
0642:             */
0643:            public RIssueTypeOption addRIssueTypeOption(AttributeOption option)
0644:                    throws TorqueException {
0645:                RIssueTypeOption rio = new RIssueTypeOption();
0646:                rio.setIssueTypeId(getIssueTypeId());
0647:                rio.setOptionId(option.getOptionId());
0648:                rio.setOrder(getLastAttributeOption(option.getAttribute()) + 1);
0649:                rio.save();
0650:                getRIssueTypeOptions(option.getAttribute(), false).add(rio);
0651:                return rio;
0652:            }
0653:
0654:            /**
0655:             * Gets associated attribute options.
0656:             */
0657:            public List getRIssueTypeOptions(Attribute attribute)
0658:                    throws TorqueException {
0659:                return getRIssueTypeOptions(attribute, true);
0660:            }
0661:
0662:            /**
0663:             * Gets associated attribute options.
0664:             */
0665:            public List getRIssueTypeOptions(Attribute attribute,
0666:                    boolean activeOnly) throws TorqueException {
0667:                List allRIssueTypeOptions = null;
0668:                allRIssueTypeOptions = getAllRIssueTypeOptions(attribute);
0669:
0670:                if (allRIssueTypeOptions != null) {
0671:                    if (activeOnly) {
0672:                        List activeRIssueTypeOptions = new ArrayList(
0673:                                allRIssueTypeOptions.size());
0674:                        for (int i = 0; i < allRIssueTypeOptions.size(); i++) {
0675:                            RIssueTypeOption rio = (RIssueTypeOption) allRIssueTypeOptions
0676:                                    .get(i);
0677:                            if (rio.getActive()) {
0678:                                activeRIssueTypeOptions.add(rio);
0679:                            }
0680:                        }
0681:                        allRIssueTypeOptions = activeRIssueTypeOptions;
0682:                    }
0683:                }
0684:                return allRIssueTypeOptions;
0685:            }
0686:
0687:            private List getAllRIssueTypeOptions(Attribute attribute)
0688:                    throws TorqueException {
0689:                List rIssueTypeOpts;
0690:                Object obj = ScarabCache.get(this , GET_ALL_R_ISSUETYPE_OPTIONS,
0691:                        attribute);
0692:                if (obj == null) {
0693:                    List options = attribute.getAttributeOptions(false);
0694:                    Integer[] optIds = null;
0695:                    if (options == null) {
0696:                        optIds = new Integer[0];
0697:                    } else {
0698:                        optIds = new Integer[options.size()];
0699:                    }
0700:                    for (int i = optIds.length - 1; i >= 0; i--) {
0701:                        optIds[i] = ((AttributeOption) options.get(i))
0702:                                .getOptionId();
0703:                    }
0704:
0705:                    if (optIds.length > 0) {
0706:                        Criteria crit = new Criteria();
0707:                        crit.add(RIssueTypeOptionPeer.ISSUE_TYPE_ID,
0708:                                getIssueTypeId());
0709:                        crit.addIn(RIssueTypeOptionPeer.OPTION_ID, optIds);
0710:                        crit.addJoin(RIssueTypeOptionPeer.OPTION_ID,
0711:                                AttributeOptionPeer.OPTION_ID);
0712:                        crit
0713:                                .addAscendingOrderByColumn(RIssueTypeOptionPeer.PREFERRED_ORDER);
0714:                        crit
0715:                                .addAscendingOrderByColumn(AttributeOptionPeer.OPTION_NAME);
0716:                        rIssueTypeOpts = RIssueTypeOptionPeer.doSelect(crit);
0717:                    } else {
0718:                        rIssueTypeOpts = new ArrayList(0);
0719:                    }
0720:                    ScarabCache.put(rIssueTypeOpts, this ,
0721:                            GET_ALL_R_ISSUETYPE_OPTIONS, attribute);
0722:                } else {
0723:                    rIssueTypeOpts = (List) obj;
0724:                }
0725:                return rIssueTypeOpts;
0726:            }
0727:
0728:            public RIssueTypeOption getRIssueTypeOption(AttributeOption option)
0729:                    throws TorqueException {
0730:                RIssueTypeOption rio = null;
0731:                List rios = getRIssueTypeOptions(option.getAttribute(), false);
0732:                Iterator i = rios.iterator();
0733:                while (i.hasNext()) {
0734:                    rio = (RIssueTypeOption) i.next();
0735:                    if (rio.getAttributeOption().equals(option)) {
0736:                        break;
0737:                    }
0738:                }
0739:
0740:                return rio;
0741:            }
0742:
0743:            /**
0744:             * Gets a list of all of the global Attributes that are not 
0745:             * Associated with this issue type
0746:             */
0747:            public List getAvailableAttributes(String attributeType)
0748:                    throws TorqueException {
0749:                List allAttributes = AttributePeer.getAttributes(attributeType);
0750:                List availAttributes = new ArrayList();
0751:                List rIssueTypeAttributes = getRIssueTypeAttributes(false,
0752:                        attributeType);
0753:                List attrs = new ArrayList();
0754:                for (int i = 0; i < rIssueTypeAttributes.size(); i++) {
0755:                    attrs.add(((RIssueTypeAttribute) rIssueTypeAttributes
0756:                            .get(i)).getAttribute());
0757:                }
0758:                for (int i = 0; i < allAttributes.size(); i++) {
0759:                    Attribute att = (Attribute) allAttributes.get(i);
0760:                    if (!attrs.contains(att)) {
0761:                        availAttributes.add(att);
0762:                    }
0763:                }
0764:                return availAttributes;
0765:            }
0766:
0767:            /**
0768:             * Gets a list of all of the global attributes options
0769:             *  that are not associated with this issue type
0770:             */
0771:            public List getAvailableAttributeOptions(Attribute attribute)
0772:                    throws TorqueException {
0773:                List rIssueTypeOptions = getRIssueTypeOptions(attribute, false);
0774:                List issueTypeOptions = new ArrayList();
0775:                if (rIssueTypeOptions != null) {
0776:                    for (int i = 0; i < rIssueTypeOptions.size(); i++) {
0777:                        issueTypeOptions
0778:                                .add(((RIssueTypeOption) rIssueTypeOptions
0779:                                        .get(i)).getAttributeOption());
0780:                    }
0781:                }
0782:
0783:                List allOptions = attribute.getAttributeOptions(false);
0784:                List availOptions = new ArrayList();
0785:
0786:                for (int i = 0; i < allOptions.size(); i++) {
0787:                    AttributeOption option = (AttributeOption) allOptions
0788:                            .get(i);
0789:                    if (!issueTypeOptions.contains(option)) {
0790:                        availOptions.add(option);
0791:                    }
0792:                }
0793:                return availOptions;
0794:            }
0795:
0796:            private MethodResultCache getMethodResult() {
0797:                return IssueTypeManager.getMethodResult();
0798:            }
0799:
0800:            public String toString() {
0801:                return '{' + super .toString() + ": name=" + getName() + '}';
0802:            }
0803:
0804:            /**
0805:             * Gets a list of non-user AttributeValues which match a given Module.
0806:             * It is used in the MoveIssue2.vm template
0807:             */
0808:            public List getMatchingAttributeValuesList(Module oldModule,
0809:                    Module newModule, IssueType newIssueType)
0810:                    throws TorqueException {
0811:                List matchingAttributes = new ArrayList();
0812:                List srcActiveAttrs = getActiveAttributes(oldModule);
0813:                List destActiveAttrs = newIssueType
0814:                        .getActiveAttributes(newModule);
0815:                for (int i = 0; i < srcActiveAttrs.size(); i++) {
0816:                    Attribute attr = (Attribute) srcActiveAttrs.get(i);
0817:
0818:                    if (destActiveAttrs.contains(attr)) {
0819:                        matchingAttributes.add(attr);
0820:                    }
0821:                }
0822:                return matchingAttributes;
0823:            }
0824:
0825:            /**
0826:             * Gets a list of Attributes which do not match a given Module.
0827:             * It is used in the MoveIssue2.vm template
0828:             */
0829:            public List getOrphanAttributeValuesList(Module oldModule,
0830:                    Module newModule, IssueType newIssueType)
0831:                    throws TorqueException {
0832:                List orphanAttributes = new ArrayList();
0833:                List srcActiveAttrs = getActiveAttributes(oldModule);
0834:                List destActiveAttrs = newIssueType
0835:                        .getActiveAttributes(newModule);
0836:                for (int i = 0; i < srcActiveAttrs.size(); i++) {
0837:                    Attribute attr = (Attribute) srcActiveAttrs.get(i);
0838:                    if (!destActiveAttrs.contains(attr)) {
0839:                        orphanAttributes.add(attr);
0840:                    }
0841:                }
0842:                return orphanAttributes;
0843:            }
0844:
0845:            /**
0846:             * Checks if this Issue Type is system defined.
0847:             * Such Issue types are specified in "IssueTypeConfig.properties"
0848:             * file in the format "<SCARAB_ISSUE_TYPE.NAME>=system"
0849:             *
0850:             * @return True if this Issue Type is System defined. False otherwise
0851:             */
0852:            public boolean isSystemDefined() throws TorqueException {
0853:                boolean systemDefined = false;
0854:                String name = getName();
0855:                if (name != null) {
0856:                    systemDefined = "system".equalsIgnoreCase(SYSTEM_CONFIG
0857:                            .getProperty(name));
0858:                }
0859:                return systemDefined;
0860:            }
0861:
0862:            /**
0863:             * if an RMA is the chosen attribute for email subjects then return it.
0864:             * if not explicitly chosen, choose the highest ordered text attribute.
0865:             *
0866:             * @return the Attribute to use as the email subject,
0867:             * or null if no suitable Attribute could be found. 
0868:             */
0869:            public Attribute getDefaultTextAttribute(Module module)
0870:                    throws TorqueException {
0871:                Attribute result = null;
0872:                Object obj = ScarabCache.get(this , GET_DEFAULT_TEXT_ATTRIBUTE);
0873:                if (obj == null) {
0874:                    // get related RMAs
0875:                    Criteria crit = new Criteria().add(
0876:                            RModuleAttributePeer.MODULE_ID, module
0877:                                    .getModuleId());
0878:                    crit
0879:                            .addAscendingOrderByColumn(RModuleAttributePeer.PREFERRED_ORDER);
0880:                    List rmas = getRModuleAttributes(crit);
0881:
0882:                    // the code to find the correct attribute could be quite simple by
0883:                    // looping and calling RMA.isDefaultText().  The code from
0884:                    // that method can be restructured here to more efficiently
0885:                    // answer this question.
0886:                    Iterator i = rmas.iterator();
0887:                    while (i.hasNext()) {
0888:                        RModuleAttribute rma = (RModuleAttribute) i.next();
0889:                        if (rma.getDefaultTextFlag()) {
0890:                            result = rma.getAttribute();
0891:                            break;
0892:                        }
0893:                    }
0894:
0895:                    if (result == null) {
0896:                        // locate the highest ranked text attribute
0897:                        i = rmas.iterator();
0898:                        while (i.hasNext()) {
0899:                            RModuleAttribute rma = (RModuleAttribute) i.next();
0900:                            Attribute testAttr = rma.getAttribute();
0901:                            if (testAttr.isTextAttribute()
0902:                                    && getAttributeGroup(module, testAttr)
0903:                                            .getActive()) {
0904:                                result = testAttr;
0905:                                break;
0906:                            }
0907:                        }
0908:                    }
0909:                    ScarabCache.put(result, this , GET_DEFAULT_TEXT_ATTRIBUTE);
0910:                } else {
0911:                    result = (Attribute) obj;
0912:                }
0913:                return result;
0914:            }
0915:
0916:            /**
0917:             * Array of Attributes used for quick search.
0918:             *
0919:             * @return an <code>List</code> of Attribute objects
0920:             */
0921:            public List getQuickSearchAttributes(Module module)
0922:                    throws TorqueException {
0923:                List attributes = null;
0924:                Object obj = ScarabCache.get(this , GET_QUICK_SEARCH_ATTRIBUTES,
0925:                        module);
0926:                if (obj == null) {
0927:                    Criteria crit = new Criteria(3).add(
0928:                            RModuleAttributePeer.QUICK_SEARCH, true);
0929:                    addOrderByClause(crit, module);
0930:                    attributes = getAttributes(crit);
0931:                    ScarabCache.put(attributes, this ,
0932:                            GET_QUICK_SEARCH_ATTRIBUTES, module);
0933:                } else {
0934:                    attributes = (List) obj;
0935:                }
0936:                return attributes;
0937:            }
0938:
0939:            /**
0940:             * gets a list of all of the Attributes in a Module based on the Criteria.
0941:             */
0942:            private List getAttributes(final Criteria criteria)
0943:                    throws TorqueException {
0944:                final List moduleAttributes = getRModuleAttributes(criteria);
0945:                final List attributes = new ArrayList(moduleAttributes.size());
0946:                for (int i = 0; i < moduleAttributes.size(); i++) {
0947:                    attributes.add(((RModuleAttribute) moduleAttributes.get(i))
0948:                            .getAttribute());
0949:                }
0950:                return attributes;
0951:            }
0952:
0953:            /**
0954:             * Checks whether the current user can create issues of this issueType
0955:             * in the given module. Currently we only check whether the user is
0956:             * allowed to create all necessary input (i.e. the required attributes).
0957:             * If at least one attribute can not be set by the user due to transition
0958:             * constraints, this method returns false, otherwise true.
0959:             * @param user
0960:             * @param module
0961:             * @return
0962:             * @throws TorqueException
0963:             * @throws ScarabException
0964:             */
0965:            public boolean canCreateIssueInScope(ScarabUser user, Module module)
0966:                    throws TorqueException, ScarabException {
0967:                boolean result = true;
0968:                List requiredAttributes = getRequiredAttributes(module);
0969:                Iterator iter = requiredAttributes.iterator();
0970:                while (iter.hasNext()) {
0971:                    Attribute attribute = (Attribute) iter.next();
0972:                    Workflow workflow = WorkflowFactory.getInstance();
0973:                    if (attribute.isOptionAttribute()) {
0974:                        boolean canDoPartial = workflow.canMakeTransitionsFrom(
0975:                                user, this , attribute, null);
0976:                        if (!canDoPartial) {
0977:                            result = false;
0978:                            break;
0979:                        }
0980:                    }
0981:                }
0982:                return result;
0983:            }
0984:
0985:            /**
0986:             * Checks whether the current user is allowed to set the given attribute
0987:             * in the given module and in this issueType. If due to transition rules
0988:             * the user is not allowed to set the attribute value, this method returns
0989:             * false, otherwise true.
0990:             * @param user
0991:             * @param module
0992:             * @param attribute
0993:             * @return
0994:             * @throws TorqueException
0995:             * @throws ScarabException
0996:             */
0997:            public boolean canCreateAttributeInScope(ScarabUser user,
0998:                    Module module, Attribute attribute) throws TorqueException,
0999:                    ScarabException {
1000:                boolean result = true;
1001:                Workflow workflow = WorkflowFactory.getInstance();
1002:                if (attribute.isOptionAttribute()) {
1003:                    result = workflow.canMakeTransitionsFrom(user, this ,
1004:                            attribute, null);
1005:                }
1006:                return result;
1007:            }
1008:
1009:            /**
1010:             * Array of Attributes which are active and required by this module.
1011:             * Whose attribute group's are also active.
1012:             * @return an <code>List</code> of Attribute objects
1013:             */
1014:            public List getRequiredAttributes(Module module)
1015:                    throws TorqueException {
1016:
1017:                List attributes = null;
1018:                Object obj = ScarabCache.get(this , GET_REQUIRED_ATTRIBUTES,
1019:                        module);
1020:                if (obj == null) {
1021:                    Criteria crit = new Criteria(3).add(
1022:                            RModuleAttributePeer.REQUIRED, true);
1023:                    crit.add(RModuleAttributePeer.ACTIVE, true);
1024:                    addOrderByClause(crit, module);
1025:                    List temp = getAttributes(crit);
1026:                    List requiredAttributes = new ArrayList();
1027:                    for (int i = 0; i < temp.size(); i++) {
1028:                        Attribute att = (Attribute) temp.get(i);
1029:                        AttributeGroup group = getAttributeGroup(module, att);
1030:                        if (group != null && group.getActive()) {
1031:                            requiredAttributes.add(att);
1032:                        }
1033:                    }
1034:                    attributes = requiredAttributes;
1035:                    ScarabCache.put(attributes, this , GET_REQUIRED_ATTRIBUTES,
1036:                            module);
1037:                } else {
1038:                    attributes = (List) obj;
1039:                }
1040:                return attributes;
1041:
1042:            }
1043:
1044:            /**
1045:             * Array of active Attributes for an issue type.
1046:             *
1047:             * @return an <code>List</code> of Attribute objects
1048:             */
1049:            public List getActiveAttributes(final Module module)
1050:                    throws TorqueException {
1051:                List attributes = null;
1052:                Object obj = ScarabCache.get(this , GET_ACTIVE_ATTRIBUTES,
1053:                        module);
1054:                if (obj == null) {
1055:                    final Criteria crit = new Criteria(2);
1056:                    crit.add(RModuleAttributePeer.ACTIVE, true);
1057:                    addOrderByClause(crit, module);
1058:                    attributes = getAttributes(crit);
1059:                    ScarabCache.put(attributes, this , GET_ACTIVE_ATTRIBUTES,
1060:                            module);
1061:                } else {
1062:                    attributes = (List) obj;
1063:                }
1064:                return attributes;
1065:            }
1066:
1067:            private void addOrderByClause(Criteria crit, Module module) {
1068:                crit
1069:                        .addAscendingOrderByColumn(RModuleAttributePeer.PREFERRED_ORDER);
1070:                crit
1071:                        .addAscendingOrderByColumn(RModuleAttributePeer.DISPLAY_VALUE);
1072:                crit.add(RModuleAttributePeer.MODULE_ID, module.getModuleId());
1073:            }
1074:
1075:            private AttributeGroup getAttributeGroup(Module module,
1076:                    Attribute attribute) throws TorqueException {
1077:                AttributeGroup group = null;
1078:                Object obj = ScarabCache.get(this , GET_ATTRIBUTE_GROUP, module,
1079:                        attribute);
1080:                if (obj == null) {
1081:                    Criteria crit = new Criteria().add(
1082:                            AttributeGroupPeer.ISSUE_TYPE_ID, getIssueTypeId())
1083:                            .add(AttributeGroupPeer.MODULE_ID,
1084:                                    module.getModuleId()).addJoin(
1085:                                    RAttributeAttributeGroupPeer.GROUP_ID,
1086:                                    AttributeGroupPeer.ATTRIBUTE_GROUP_ID).add(
1087:                                    RAttributeAttributeGroupPeer.ATTRIBUTE_ID,
1088:                                    attribute.getAttributeId());
1089:                    List results = AttributeGroupPeer.doSelect(crit);
1090:                    if (results.size() > 0) {
1091:                        group = (AttributeGroup) results.get(0);
1092:                        ScarabCache.put(group, this , GET_ATTRIBUTE_GROUP,
1093:                                module, attribute);
1094:                    }
1095:                } else {
1096:                    group = (AttributeGroup) obj;
1097:                }
1098:                return group;
1099:            }
1100:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.