Source Code Cross Referenced for KualiMaintainableImpl.java in  » ERP-CRM-Financial » Kuali-Financial-System » org » kuali » core » maintenance » 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 » ERP CRM Financial » Kuali Financial System » org.kuali.core.maintenance 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2005-2007 The Kuali Foundation.
0003:         * 
0004:         * Licensed under the Educational Community License, Version 1.0 (the "License");
0005:         * you may not use this file except in compliance with the License.
0006:         * You may obtain a copy of the License at
0007:         * 
0008:         * http://www.opensource.org/licenses/ecl1.php
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS,
0012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013:         * See the License for the specific language governing permissions and
0014:         * limitations under the License.
0015:         */
0016:        package org.kuali.core.maintenance;
0017:
0018:        import java.beans.PropertyDescriptor;
0019:        import java.io.Serializable;
0020:        import java.security.GeneralSecurityException;
0021:        import java.util.ArrayList;
0022:        import java.util.Collection;
0023:        import java.util.HashMap;
0024:        import java.util.HashSet;
0025:        import java.util.Iterator;
0026:        import java.util.List;
0027:        import java.util.Map;
0028:        import java.util.Set;
0029:
0030:        import org.apache.commons.beanutils.PropertyUtils;
0031:        import org.apache.commons.lang.StringUtils;
0032:        import org.kuali.RiceConstants;
0033:        import org.kuali.RicePropertyConstants;
0034:        import org.kuali.core.bo.BusinessObject;
0035:        import org.kuali.core.bo.BusinessObjectRelationship;
0036:        import org.kuali.core.bo.DocumentHeader;
0037:        import org.kuali.core.bo.PersistableBusinessObject;
0038:        import org.kuali.core.datadictionary.DataDictionaryDefinitionBase;
0039:        import org.kuali.core.datadictionary.MaintainableCollectionDefinition;
0040:        import org.kuali.core.datadictionary.MaintainableFieldDefinition;
0041:        import org.kuali.core.datadictionary.MaintainableItemDefinition;
0042:        import org.kuali.core.datadictionary.MaintainableSectionDefinition;
0043:        import org.kuali.core.document.MaintenanceDocument;
0044:        import org.kuali.core.document.MaintenanceLock;
0045:        import org.kuali.core.lookup.LookupUtils;
0046:        import org.kuali.core.service.BusinessObjectMetaDataService;
0047:        import org.kuali.core.service.DataDictionaryService;
0048:        import org.kuali.core.service.EncryptionService;
0049:        import org.kuali.core.service.PersistenceStructureService;
0050:        import org.kuali.core.util.FieldUtils;
0051:        import org.kuali.core.util.GlobalVariables;
0052:        import org.kuali.core.util.InactiveRecordsHidingUtils;
0053:        import org.kuali.core.util.MaintenanceUtils;
0054:        import org.kuali.core.util.ObjectUtils;
0055:        import org.kuali.core.web.ui.Section;
0056:        import org.kuali.core.web.ui.SectionBridge;
0057:        import org.kuali.rice.KNSServiceLocator;
0058:
0059:        /**
0060:         * Base Maintainable class to hold things common to all maintainables.
0061:         */
0062:        public class KualiMaintainableImpl implements  Maintainable,
0063:                Serializable {
0064:            private static final long serialVersionUID = 4814145799502207182L;
0065:
0066:            private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
0067:                    .getLogger(KualiMaintainableImpl.class);
0068:
0069:            protected String documentNumber;
0070:            protected PersistableBusinessObject businessObject;
0071:            protected Class boClass;
0072:            protected String maintenanceAction;
0073:            protected boolean generateDefaultValues;
0074:            protected boolean generateBlankRequiredValues;
0075:
0076:            protected Map<String, PersistableBusinessObject> newCollectionLines = new HashMap<String, PersistableBusinessObject>();
0077:            protected Map<String, Boolean> inactiveRecordDisplay = new HashMap<String, Boolean>();
0078:
0079:            private String docTypeName;
0080:
0081:            /**
0082:             * Default empty constructor
0083:             */
0084:            public KualiMaintainableImpl() {
0085:            }
0086:
0087:            /**
0088:             * Constructor which initializes the business object to be maintained.
0089:             * 
0090:             * @param businessObject
0091:             */
0092:            public KualiMaintainableImpl(
0093:                    PersistableBusinessObject businessObject) {
0094:                this ();
0095:                this .businessObject = businessObject;
0096:            }
0097:
0098:            public void setupNewFromExisting() {
0099:
0100:            }
0101:
0102:            /**
0103:             * This is a hook to allow the document to override the generic document title.
0104:             * 
0105:             * @return String   document title
0106:             */
0107:            public String getDocumentTitle(MaintenanceDocument document) {
0108:                //default implementation is to allow MaintenanceDocumentBase to generate the doc title
0109:                return "";
0110:            }
0111:
0112:            /**
0113:             * Note: as currently implemented, every key field for a given BusinessObject subclass must have a visible getter.
0114:             * 
0115:             * @return String containing the business object class and key value pairs of the current instance that can be used as a unique
0116:             *         locking representation.
0117:             */
0118:            public List<MaintenanceLock> generateMaintenanceLocks() {
0119:
0120:                //NOTE: KualiGlobalMaintainableImpl overrides this method and forces all globals to override that, so they each do their own thing
0121:
0122:                List<MaintenanceLock> maintenanceLocks = new ArrayList<MaintenanceLock>();
0123:                StringBuffer lockRepresentation = new StringBuffer(boClass
0124:                        .getName());
0125:                lockRepresentation
0126:                        .append(RiceConstants.Maintenance.AFTER_CLASS_DELIM);
0127:
0128:                PersistableBusinessObject bo = getBusinessObject();
0129:                List keyFieldNames = KNSServiceLocator
0130:                        .getMaintenanceDocumentDictionaryService()
0131:                        .getLockingKeys(getDocumentTypeName());
0132:
0133:                for (Iterator i = keyFieldNames.iterator(); i.hasNext();) {
0134:                    String fieldName = (String) i.next();
0135:                    Object fieldValue = ObjectUtils.getPropertyValue(bo,
0136:                            fieldName);
0137:                    if (fieldValue == null) {
0138:                        fieldValue = "";
0139:                    }
0140:
0141:                    // check if field is a secure
0142:                    String displayWorkgroup = KNSServiceLocator
0143:                            .getDataDictionaryService()
0144:                            .getAttributeDisplayWorkgroup(getBoClass(),
0145:                                    fieldName);
0146:                    if (StringUtils.isNotBlank(displayWorkgroup)) {
0147:                        try {
0148:                            fieldValue = KNSServiceLocator
0149:                                    .getEncryptionService().encrypt(fieldValue);
0150:                        } catch (GeneralSecurityException e) {
0151:                            LOG
0152:                                    .error("Unable to encrypt secure field for locking representation "
0153:                                            + e.getMessage());
0154:                            throw new RuntimeException(
0155:                                    "Unable to encrypt secure field for locking representation "
0156:                                            + e.getMessage());
0157:                        }
0158:                    }
0159:
0160:                    lockRepresentation.append(fieldName);
0161:                    lockRepresentation
0162:                            .append(RiceConstants.Maintenance.AFTER_FIELDNAME_DELIM);
0163:                    lockRepresentation.append(String.valueOf(fieldValue));
0164:                    if (i.hasNext()) {
0165:                        lockRepresentation
0166:                                .append(RiceConstants.Maintenance.AFTER_VALUE_DELIM);
0167:                    }
0168:                }
0169:
0170:                MaintenanceLock maintenanceLock = new MaintenanceLock();
0171:                maintenanceLock.setDocumentNumber(documentNumber);
0172:                maintenanceLock.setLockingRepresentation(lockRepresentation
0173:                        .toString());
0174:                maintenanceLocks.add(maintenanceLock);
0175:                return maintenanceLocks;
0176:            }
0177:
0178:            /**
0179:             * @see org.kuali.core.maintenance.Maintainable#populateBusinessObject(java.util.Map)
0180:             */
0181:            public Map populateBusinessObject(Map fieldValues) {
0182:                fieldValues = decryptEncryptedData(fieldValues);
0183:                Map newFieldValues = null;
0184:                newFieldValues = KNSServiceLocator.getUniversalUserService()
0185:                        .resolveUserIdentifiersToUniversalIdentifiers(
0186:                                getBusinessObject(), fieldValues);
0187:
0188:                Map cachedValues = FieldUtils.populateBusinessObjectFromMap(
0189:                        getBusinessObject(), newFieldValues);
0190:                KNSServiceLocator.getBusinessObjectDictionaryService()
0191:                        .performForceUppercase(getBusinessObject());
0192:                return cachedValues;
0193:            }
0194:
0195:            /**
0196:             * Special hidden parameters are set on the maintenance jsp starting with a prefix that tells us which fields have been
0197:             * encrypted. This field finds the those parameters in the map, whose value gives us the property name that has an encrypted
0198:             * value. We then need to decrypt the value in the Map before the business object is populated.
0199:             * 
0200:             * @param fieldValues - possibly with encrypted values
0201:             * @return Map fieldValues - with no encrypted values
0202:             */
0203:            private Map decryptEncryptedData(Map fieldValues) {
0204:                try {
0205:                    for (Iterator iter = fieldValues.keySet().iterator(); iter
0206:                            .hasNext();) {
0207:                        String fieldName = (String) iter.next();
0208:                        String fieldValue = (String) fieldValues.get(fieldName);
0209:                        if (fieldValue != null
0210:                                && fieldValue
0211:                                        .endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
0212:                            String encryptedValue = fieldValue;
0213:
0214:                            // take of the postfix
0215:                            encryptedValue = StringUtils.stripEnd(
0216:                                    encryptedValue,
0217:                                    EncryptionService.ENCRYPTION_POST_PREFIX);
0218:                            String decryptedValue = KNSServiceLocator
0219:                                    .getEncryptionService().decrypt(
0220:                                            encryptedValue);
0221:
0222:                            fieldValues.put(fieldName, decryptedValue);
0223:                        }
0224:                    }
0225:                } catch (GeneralSecurityException e) {
0226:                    throw new RuntimeException(
0227:                            "Unable to decrypt secure data: " + e.getMessage());
0228:                }
0229:
0230:                return fieldValues;
0231:            }
0232:
0233:            /**
0234:             * Calls method to get all the core sections for the business object defined in the data dictionary. Then determines if the bo
0235:             * has custom attributes, if so builds a custom attribute section and adds to the section list.
0236:             * 
0237:             * @return List of org.kuali.ui.Section objects
0238:             */
0239:            public List getSections(Maintainable oldMaintainable) {
0240:                List<Section> sections = new ArrayList<Section>();
0241:                sections.addAll(getCoreSections(oldMaintainable));
0242:
0243:                return sections;
0244:            }
0245:
0246:            /**
0247:             * Gets list of maintenance sections built from the data dictionary. If the section contains maintenance fields, construct
0248:             * Row/Field UI objects and place under Section UI. If section contains a maintenance collection, call method to build a Section
0249:             * UI which contains rows of Container Fields.
0250:             * 
0251:             * @return List of org.kuali.ui.Section objects
0252:             */
0253:            public List<Section> getCoreSections(Maintainable oldMaintainable) {
0254:
0255:                List<Section> sections = new ArrayList<Section>();
0256:
0257:                List<MaintainableSectionDefinition> sectionDefinitions = KNSServiceLocator
0258:                        .getMaintenanceDocumentDictionaryService()
0259:                        .getMaintainableSections(docTypeName);
0260:
0261:                try {
0262:                    // iterate through section definitions and create Section UI object
0263:                    for (Iterator iter = sectionDefinitions.iterator(); iter
0264:                            .hasNext();) {
0265:
0266:                        MaintainableSectionDefinition maintSectionDef = (MaintainableSectionDefinition) iter
0267:                                .next();
0268:
0269:                        List<String> displayedFieldNames = new ArrayList<String>();
0270:
0271:                        for (Iterator iter2 = maintSectionDef
0272:                                .getMaintainableItems().iterator(); iter2
0273:                                .hasNext();) {
0274:
0275:                            MaintainableItemDefinition item = (MaintainableItemDefinition) iter2
0276:                                    .next();
0277:                            if (item instanceof  MaintainableFieldDefinition) {
0278:                                displayedFieldNames
0279:                                        .add(((MaintainableFieldDefinition) item)
0280:                                                .getName());
0281:                            }
0282:                        }
0283:
0284:                        Section section = SectionBridge.toSection(
0285:                                maintSectionDef, getBusinessObject(), this ,
0286:                                oldMaintainable, getMaintenanceAction(),
0287:                                isGenerateDefaultValues(),
0288:                                isGenerateBlankRequiredValues(),
0289:                                displayedFieldNames);
0290:
0291:                        // add to section list
0292:                        sections.add(section);
0293:
0294:                    }
0295:
0296:                } catch (InstantiationException e) {
0297:                    LOG.error("Unable to create instance of object class"
0298:                            + e.getMessage());
0299:                    throw new RuntimeException(
0300:                            "Unable to create instance of object class"
0301:                                    + e.getMessage());
0302:                } catch (IllegalAccessException e) {
0303:                    LOG.error("Unable to create instance of object class"
0304:                            + e.getMessage());
0305:                    throw new RuntimeException(
0306:                            "Unable to create instance of object class"
0307:                                    + e.getMessage());
0308:                }
0309:
0310:                return sections;
0311:            }
0312:
0313:            /**
0314:             * 
0315:             * @see org.kuali.core.maintenance.Maintainable#saveBusinessObject()
0316:             */
0317:            public void saveBusinessObject() {
0318:                KNSServiceLocator.getBusinessObjectService().linkAndSave(
0319:                        businessObject);
0320:            }
0321:
0322:            /**
0323:             * Retrieves title for maintenance document from data dictionary
0324:             */
0325:            public String getMaintainableTitle() {
0326:                return KNSServiceLocator
0327:                        .getMaintenanceDocumentDictionaryService()
0328:                        .getMaintenanceLabel(getDocumentTypeName());
0329:            }
0330:
0331:            /**
0332:             * Retrieves the status of the boNotesEnabled
0333:             */
0334:            public boolean isBoNotesEnabled() {
0335:                return KNSServiceLocator.getBusinessObjectDictionaryService()
0336:                        .areNotesSupported(this .boClass);
0337:            }
0338:
0339:            /**
0340:             * @see org.kuali.core.maintenance.Maintainable#refresh(java.lang.String, java.util.Map) Impls will be needed if custom action
0341:             *      is needed on refresh.
0342:             */
0343:            public void refresh(String refreshCaller, Map fieldValues,
0344:                    MaintenanceDocument document) {
0345:                String referencesToRefresh = (String) fieldValues
0346:                        .get(RiceConstants.REFERENCES_TO_REFRESH);
0347:                refreshReferences(referencesToRefresh);
0348:            }
0349:
0350:            protected void refreshReferences(String referencesToRefresh) {
0351:                PersistenceStructureService persistenceStructureService = KNSServiceLocator
0352:                        .getPersistenceStructureService();
0353:                if (StringUtils.isNotBlank(referencesToRefresh)) {
0354:                    String[] references = StringUtils.split(
0355:                            referencesToRefresh,
0356:                            RiceConstants.REFERENCES_TO_REFRESH_SEPARATOR);
0357:                    for (String reference : references) {
0358:                        if (StringUtils.isNotBlank(reference)) {
0359:                            if (reference.startsWith(RiceConstants.ADD_PREFIX
0360:                                    + ".")) {
0361:                                // add one for the period
0362:                                reference = reference
0363:                                        .substring(RiceConstants.ADD_PREFIX
0364:                                                .length() + 1);
0365:
0366:                                String boToRefreshName = StringUtils
0367:                                        .substringBeforeLast(reference, ".");
0368:                                String propertyToRefresh = StringUtils
0369:                                        .substringAfterLast(reference, ".");
0370:                                if (StringUtils.isNotBlank(propertyToRefresh)) {
0371:                                    PersistableBusinessObject addlineBO = getNewCollectionLine(boToRefreshName);
0372:                                    Class addlineBOClass = addlineBO.getClass();
0373:                                    if (LOG.isDebugEnabled()) {
0374:                                        LOG
0375:                                                .debug("Refresh this \"new\"/add object for the collections:  "
0376:                                                        + reference);
0377:                                    }
0378:                                    if (persistenceStructureService
0379:                                            .hasReference(addlineBOClass,
0380:                                                    propertyToRefresh)
0381:                                            || persistenceStructureService
0382:                                                    .hasCollection(
0383:                                                            addlineBOClass,
0384:                                                            propertyToRefresh)) {
0385:                                        addlineBO
0386:                                                .refreshReferenceObject(propertyToRefresh);
0387:                                    } else {
0388:                                        if (KNSServiceLocator
0389:                                                .getDataDictionaryService()
0390:                                                .hasRelationship(
0391:                                                        addlineBOClass
0392:                                                                .getName(),
0393:                                                        propertyToRefresh)) {
0394:                                            // a DD mapping, try to go straight to the object and refresh it there
0395:                                            Object possibleBO = ObjectUtils
0396:                                                    .getPropertyValue(
0397:                                                            addlineBO,
0398:                                                            propertyToRefresh);
0399:                                            if (possibleBO != null
0400:                                                    && possibleBO instanceof  PersistableBusinessObject) {
0401:                                                ((PersistableBusinessObject) possibleBO)
0402:                                                        .refresh();
0403:                                            }
0404:                                        }
0405:                                    }
0406:                                } else {
0407:                                    LOG
0408:                                            .error("Error: unable to refresh this \"new\"/add object for the collections:  "
0409:                                                    + reference);
0410:                                }
0411:                            } else if (ObjectUtils.isNestedAttribute(reference)) {
0412:                                Object nestedObject = ObjectUtils
0413:                                        .getNestedValue(
0414:                                                getBusinessObject(),
0415:                                                ObjectUtils
0416:                                                        .getNestedAttributePrefix(reference));
0417:                                if (nestedObject instanceof  Collection) {
0418:                                    // do nothing, probably because it's not really a collection reference but a relationship defined in the DD for a collections lookup
0419:                                    // this part will need to be rewritten when the DD supports true collection references   
0420:                                } else if (nestedObject instanceof  PersistableBusinessObject) {
0421:                                    String propertyToRefresh = ObjectUtils
0422:                                            .getNestedAttributePrimitive(reference);
0423:                                    if (persistenceStructureService
0424:                                            .hasReference(nestedObject
0425:                                                    .getClass(),
0426:                                                    propertyToRefresh)
0427:                                            || persistenceStructureService
0428:                                                    .hasCollection(nestedObject
0429:                                                            .getClass(),
0430:                                                            propertyToRefresh)) {
0431:                                        if (LOG.isDebugEnabled()) {
0432:                                            LOG
0433:                                                    .debug("Refeshing "
0434:                                                            + ObjectUtils
0435:                                                                    .getNestedAttributePrefix(reference)
0436:                                                            + " "
0437:                                                            + ObjectUtils
0438:                                                                    .getNestedAttributePrimitive(reference));
0439:                                        }
0440:                                        ((PersistableBusinessObject) nestedObject)
0441:                                                .refreshReferenceObject(propertyToRefresh);
0442:                                    } else {
0443:                                        // a DD mapping, try to go straight to the object and refresh it there
0444:                                        Object possibleBO = ObjectUtils
0445:                                                .getPropertyValue(nestedObject,
0446:                                                        propertyToRefresh);
0447:                                        if (possibleBO != null
0448:                                                && possibleBO instanceof  PersistableBusinessObject) {
0449:                                            if (KNSServiceLocator
0450:                                                    .getDataDictionaryService()
0451:                                                    .hasRelationship(
0452:                                                            possibleBO
0453:                                                                    .getClass()
0454:                                                                    .getName(),
0455:                                                            propertyToRefresh)) {
0456:                                                ((PersistableBusinessObject) possibleBO)
0457:                                                        .refresh();
0458:                                            }
0459:                                        }
0460:                                    }
0461:                                } else {
0462:                                    LOG
0463:                                            .warn("Expected that a referenceToRefresh ("
0464:                                                    + reference
0465:                                                    + ")  would be a PersistableBusinessObject or Collection, but instead, it was of class "
0466:                                                    + nestedObject.getClass()
0467:                                                            .getName());
0468:                                }
0469:                            } else {
0470:                                if (LOG.isDebugEnabled()) {
0471:                                    LOG.debug("Refreshing " + reference);
0472:                                }
0473:                                if (persistenceStructureService.hasReference(
0474:                                        boClass, reference)
0475:                                        || persistenceStructureService
0476:                                                .hasCollection(boClass,
0477:                                                        reference)) {
0478:                                    getBusinessObject().refreshReferenceObject(
0479:                                            reference);
0480:                                } else {
0481:                                    if (KNSServiceLocator
0482:                                            .getDataDictionaryService()
0483:                                            .hasRelationship(
0484:                                                    getBusinessObject()
0485:                                                            .getClass()
0486:                                                            .getName(),
0487:                                                    reference)) {
0488:                                        // a DD mapping, try to go straight to the object and refresh it there
0489:                                        Object possibleRelationship = ObjectUtils
0490:                                                .getPropertyValue(
0491:                                                        getBusinessObject(),
0492:                                                        reference);
0493:                                        if (possibleRelationship != null) {
0494:                                            if (possibleRelationship instanceof  PersistableBusinessObject) {
0495:                                                ((PersistableBusinessObject) possibleRelationship)
0496:                                                        .refresh();
0497:                                            } else if (possibleRelationship instanceof  Collection) {
0498:                                                // do nothing, probably because it's not really a collection reference but a relationship defined in the DD for a collections lookup
0499:                                                // this part will need to be rewritten when the DD supports true collection references   
0500:                                            } else {
0501:                                                LOG
0502:                                                        .warn("Expected that a referenceToRefresh ("
0503:                                                                + reference
0504:                                                                + ")  would be a PersistableBusinessObject or Collection, but instead, it was of class "
0505:                                                                + possibleRelationship
0506:                                                                        .getClass()
0507:                                                                        .getName());
0508:                                            }
0509:                                        }
0510:                                    }
0511:                                }
0512:                            }
0513:                        }
0514:                    }
0515:                }
0516:            }
0517:
0518:            public void addMultipleValueLookupResults(
0519:                    MaintenanceDocument document, String collectionName,
0520:                    Collection<PersistableBusinessObject> rawValues) {
0521:                PersistableBusinessObject bo = document
0522:                        .getNewMaintainableObject().getBusinessObject();
0523:                Collection maintCollection = (Collection) ObjectUtils
0524:                        .getPropertyValue(bo, collectionName);
0525:                String docTypeName = document.getDocumentHeader()
0526:                        .getWorkflowDocument().getDocumentType();
0527:
0528:                List<String> duplicateIdentifierFieldsFromDataDictionary = getDuplicateIdentifierFieldsFromDataDictionary(
0529:                        docTypeName, collectionName);
0530:
0531:                List<String> existingIdentifierList = getMultiValueIdentifierList(
0532:                        maintCollection,
0533:                        duplicateIdentifierFieldsFromDataDictionary);
0534:
0535:                Class collectionClass = KNSServiceLocator
0536:                        .getMaintenanceDocumentDictionaryService()
0537:                        .getCollectionBusinessObjectClass(docTypeName,
0538:                                collectionName);
0539:
0540:                List<MaintainableSectionDefinition> sections = KNSServiceLocator
0541:                        .getMaintenanceDocumentDictionaryService()
0542:                        .getMaintainableSections(docTypeName);
0543:                Map<String, String> template = MaintenanceUtils
0544:                        .generateMultipleValueLookupBOTemplate(sections,
0545:                                collectionName);
0546:                try {
0547:                    for (PersistableBusinessObject nextBo : rawValues) {
0548:                        PersistableBusinessObject templatedBo = (PersistableBusinessObject) ObjectUtils
0549:                                .createHybridBusinessObject(collectionClass,
0550:                                        nextBo, template);
0551:                        templatedBo.setNewCollectionRecord(true);
0552:                        prepareBusinessObjectForAdditionFromMultipleValueLookup(
0553:                                collectionName, templatedBo);
0554:                        if (!hasBusinessObjectExisted(templatedBo,
0555:                                existingIdentifierList,
0556:                                duplicateIdentifierFieldsFromDataDictionary)) {
0557:                            maintCollection.add(templatedBo);
0558:                        }
0559:                    }
0560:                } catch (Exception e) {
0561:                    LOG.error("Unable to add multiple value lookup results "
0562:                            + e.getMessage());
0563:                    throw new RuntimeException(
0564:                            "Unable to add multiple value lookup results "
0565:                                    + e.getMessage());
0566:                }
0567:            }
0568:
0569:            /**
0570:             * This method is to retrieve a List of fields which are specified in the maintenance document
0571:             * data dictionary as the duplicateIdentificationFields. This List is used to determine whether
0572:             * the new entry being added to the collection is a duplicate entry and if so, we should not
0573:             * add the new entry to the existing collection
0574:             * 
0575:             * @param docTypeName
0576:             * @param collectionName
0577:             */
0578:            public List<String> getDuplicateIdentifierFieldsFromDataDictionary(
0579:                    String docTypeName, String collectionName) {
0580:                List<String> duplicateIdentifierFieldNames = new ArrayList<String>();
0581:                MaintainableCollectionDefinition collDef = KNSServiceLocator
0582:                        .getMaintenanceDocumentDictionaryService()
0583:                        .getMaintainableCollection(docTypeName, collectionName);
0584:                Collection<MaintainableFieldDefinition> fieldDef = collDef
0585:                        .getDuplicateIdentificationFields();
0586:                for (MaintainableFieldDefinition eachFieldDef : fieldDef) {
0587:                    duplicateIdentifierFieldNames.add(eachFieldDef.getName());
0588:                }
0589:                return duplicateIdentifierFieldNames;
0590:            }
0591:
0592:            public List<String> getMultiValueIdentifierList(
0593:                    Collection maintCollection,
0594:                    List<String> duplicateIdentifierFields) {
0595:                List<String> identifierList = new ArrayList<String>();
0596:                for (PersistableBusinessObject bo : (Collection<PersistableBusinessObject>) maintCollection) {
0597:                    String uniqueIdentifier = new String();
0598:                    for (String identifierField : duplicateIdentifierFields) {
0599:                        uniqueIdentifier = uniqueIdentifier
0600:                                + identifierField
0601:                                + "-"
0602:                                + ObjectUtils.getPropertyValue(bo,
0603:                                        identifierField);
0604:                    }
0605:                    if (StringUtils.isNotEmpty(uniqueIdentifier)) {
0606:                        identifierList.add(uniqueIdentifier);
0607:                    }
0608:                }
0609:                return identifierList;
0610:            }
0611:
0612:            public boolean hasBusinessObjectExisted(BusinessObject bo,
0613:                    List<String> existingIdentifierList,
0614:                    List<String> duplicateIdentifierFields) {
0615:                String uniqueIdentifier = new String();
0616:                for (String identifierField : duplicateIdentifierFields) {
0617:                    uniqueIdentifier = uniqueIdentifier + identifierField + "-"
0618:                            + ObjectUtils.getPropertyValue(bo, identifierField);
0619:                }
0620:                if (existingIdentifierList.contains(uniqueIdentifier)) {
0621:                    return true;
0622:                } else {
0623:                    return false;
0624:                }
0625:            }
0626:
0627:            public void prepareBusinessObjectForAdditionFromMultipleValueLookup(
0628:                    String collectionName, BusinessObject bo) {
0629:                // default implementation does nothing
0630:            }
0631:
0632:            /**
0633:             * 
0634:             * @see org.kuali.core.maintenance.Maintainable#prepareForSave()
0635:             */
0636:            public void prepareForSave() {
0637:            }
0638:
0639:            /**
0640:             * 
0641:             * @see org.kuali.core.maintenance.Maintainable#processAfterRetrieve()
0642:             */
0643:            public void processAfterRetrieve() {
0644:            }
0645:
0646:            /** 
0647:             * Set the new collection records back to true so they can be deleted (copy should act like new)
0648:             * 
0649:             * @see org.kuali.core.maintenance.KualiMaintainableImpl#processAfterCopy()
0650:             */
0651:            public void processAfterCopy() {
0652:                try {
0653:                    ObjectUtils.setObjectPropertyDeep(businessObject,
0654:                            RicePropertyConstants.NEW_COLLECTION_RECORD,
0655:                            boolean.class, true, 2);
0656:                } catch (Exception e) {
0657:                    LOG.error("unable to set newCollectionRecord property: "
0658:                            + e.getMessage(), e);
0659:                    throw new RuntimeException(
0660:                            "unable to set newCollectionRecord property: "
0661:                                    + e.getMessage(), e);
0662:                }
0663:            }
0664:
0665:            /**
0666:             * @see org.kuali.core.maintenance.Maintainable#processAfterEdit()
0667:             */
0668:            public void processAfterEdit() {
0669:            }
0670:
0671:            /**
0672:             * Retrieves the document type name from the data dictionary based on business object class
0673:             */
0674:            private String getDocumentTypeName() {
0675:                return KNSServiceLocator
0676:                        .getMaintenanceDocumentDictionaryService()
0677:                        .getDocumentTypeName(boClass);
0678:            }
0679:
0680:            /**
0681:             * @return Returns the instance of the business object being maintained.
0682:             */
0683:            public PersistableBusinessObject getBusinessObject() {
0684:                return businessObject;
0685:            }
0686:
0687:            /**
0688:             * @param businessObject Sets the instance of a business object that will be maintained.
0689:             */
0690:            public void setBusinessObject(
0691:                    PersistableBusinessObject businessObject) {
0692:                this .businessObject = businessObject;
0693:            }
0694:
0695:            /**
0696:             * @return Returns the boClass.
0697:             */
0698:            public Class getBoClass() {
0699:                return boClass;
0700:            }
0701:
0702:            /**
0703:             * @param boClass The boClass to set.
0704:             */
0705:            public void setBoClass(Class boClass) {
0706:                this .boClass = boClass;
0707:                this .docTypeName = getDocumentTypeName();
0708:            }
0709:
0710:            /**
0711:             * @return Returns the maintenanceAction.
0712:             */
0713:            public String getMaintenanceAction() {
0714:                return maintenanceAction;
0715:            }
0716:
0717:            /**
0718:             * @param maintenanceAction The maintenanceAction to set.
0719:             */
0720:            public void setMaintenanceAction(String maintenanceAction) {
0721:                this .maintenanceAction = maintenanceAction;
0722:            }
0723:
0724:            /**
0725:             * @return Returns the generateDefaultValues.
0726:             */
0727:            public boolean isGenerateDefaultValues() {
0728:                return generateDefaultValues;
0729:            }
0730:
0731:            /**
0732:             * @param generateDefaultValues The generateDefaultValues to set.
0733:             */
0734:            public void setGenerateDefaultValues(boolean generateDefaultValues) {
0735:                this .generateDefaultValues = generateDefaultValues;
0736:            }
0737:
0738:            /**
0739:             * @return Returns the generateDefaultValues.
0740:             */
0741:            public boolean isGenerateBlankRequiredValues() {
0742:                return generateBlankRequiredValues;
0743:            }
0744:
0745:            /**
0746:             * @param generateDefaultValues The generateDefaultValues to set.
0747:             */
0748:            public void setGenerateBlankRequiredValues(
0749:                    boolean generateBlankRequiredValues) {
0750:                this .generateBlankRequiredValues = generateBlankRequiredValues;
0751:            }
0752:
0753:            /**
0754:             * Sets the documentNumber attribute value.
0755:             * 
0756:             * @param documentNumber The documentNumber to set.
0757:             */
0758:            public final void setDocumentNumber(String documentNumber) {
0759:                this .documentNumber = documentNumber;
0760:            }
0761:
0762:            public void processAfterAddLine(String colName, Class colClass) {
0763:            }
0764:
0765:            /**
0766:             * @see org.kuali.core.maintenance.Maintainable#getShowInactiveRecords(java.lang.String)
0767:             */
0768:            public boolean getShowInactiveRecords(String collectionName) {
0769:                return InactiveRecordsHidingUtils.getShowInactiveRecords(
0770:                        inactiveRecordDisplay, collectionName);
0771:            }
0772:
0773:            /**
0774:             * @see org.kuali.core.maintenance.Maintainable#setShowInactiveRecords(java.lang.String, boolean)
0775:             */
0776:            public void setShowInactiveRecords(String collectionName,
0777:                    boolean showInactive) {
0778:                InactiveRecordsHidingUtils.setShowInactiveRecords(
0779:                        inactiveRecordDisplay, collectionName, showInactive);
0780:            }
0781:
0782:            /**
0783:             * @return the inactiveRecordDisplay
0784:             */
0785:            public Map<String, Boolean> getInactiveRecordDisplay() {
0786:                return inactiveRecordDisplay;
0787:            }
0788:
0789:            public void addNewLineToCollection(String collectionName) {
0790:
0791:                if (LOG.isDebugEnabled()) {
0792:                    LOG.debug("addNewLineToCollection( " + collectionName
0793:                            + " )");
0794:                }
0795:                // get the new line from the map
0796:                PersistableBusinessObject addLine = newCollectionLines
0797:                        .get(collectionName);
0798:                if (addLine != null) {
0799:                    // mark the isNewCollectionRecord so the option to delete this line will be presented
0800:                    addLine.setNewCollectionRecord(true);
0801:
0802:                    //if we add back add button on sub collection of an "add line" we may need extra logic here
0803:
0804:                    // get the collection from the business object
0805:                    Collection maintCollection = (Collection) ObjectUtils
0806:                            .getPropertyValue(getBusinessObject(),
0807:                                    collectionName);
0808:                    // add the line to the collection
0809:                    maintCollection.add(addLine);
0810:                    //refresh parent object since attributes could of changed prior to user clicking add
0811:
0812:                    String referencesToRefresh = LookupUtils
0813:                            .convertReferencesToSelectCollectionToString(getAllRefreshableReferences(getBusinessObject()
0814:                                    .getClass()));
0815:                    if (LOG.isInfoEnabled()) {
0816:                        LOG
0817:                                .info("References to refresh for adding line to collection "
0818:                                        + collectionName
0819:                                        + ": "
0820:                                        + referencesToRefresh);
0821:                    }
0822:                    refreshReferences(referencesToRefresh);
0823:                }
0824:
0825:                initNewCollectionLine(collectionName);
0826:
0827:            }
0828:
0829:            public PersistableBusinessObject getNewCollectionLine(
0830:                    String collectionName) {
0831:                if (LOG.isDebugEnabled()) {
0832:                    //LOG.debug( this + ") getNewCollectionLine( " + collectionName + ")", new Exception( "tracing exception") );
0833:                    LOG.debug("newCollectionLines: " + newCollectionLines);
0834:                }
0835:                PersistableBusinessObject addLine = newCollectionLines
0836:                        .get(collectionName);
0837:                if (addLine == null) {
0838:                    addLine = initNewCollectionLine(collectionName);
0839:                }
0840:                return addLine;
0841:            }
0842:
0843:            public PersistableBusinessObject initNewCollectionLine(
0844:                    String collectionName) {
0845:                if (LOG.isDebugEnabled()) {
0846:                    LOG
0847:                            .debug("initNewCollectionLine( " + collectionName
0848:                                    + " )");
0849:                }
0850:                // try to get the object from the map
0851:                //BusinessObject addLine = newCollectionLines.get( collectionName );
0852:                //if ( addLine == null ) {
0853:                // if not there, instantiate a new one
0854:                PersistableBusinessObject addLine;
0855:                try {
0856:                    addLine = (PersistableBusinessObject) KNSServiceLocator
0857:                            .getMaintenanceDocumentDictionaryService()
0858:                            .getCollectionBusinessObjectClass(docTypeName,
0859:                                    collectionName).newInstance();
0860:                } catch (Exception ex) {
0861:                    LOG.error("unable to instantiate new collection line", ex);
0862:                    throw new RuntimeException(
0863:                            "unable to instantiate new collection line", ex);
0864:                }
0865:                // and add it to the map
0866:                newCollectionLines.put(collectionName, addLine);
0867:                //}
0868:                // set its values to the defaults
0869:                PropertyDescriptor[] descriptors = PropertyUtils
0870:                        .getPropertyDescriptors(addLine);
0871:                for (int i = 0; i < descriptors.length; ++i) {
0872:                    PropertyDescriptor propertyDescriptor = descriptors[i];
0873:
0874:                    String fieldName = propertyDescriptor.getName();
0875:                    Class propertyType = propertyDescriptor.getPropertyType();
0876:                    String value = KNSServiceLocator
0877:                            .getMaintenanceDocumentDictionaryService()
0878:                            .getCollectionFieldDefaultValue(docTypeName,
0879:                                    collectionName, fieldName);
0880:                    if (value != null) {
0881:                        try {
0882:                            ObjectUtils.setObjectProperty(addLine, fieldName,
0883:                                    propertyType, value);
0884:                        } catch (Exception ex) {
0885:                            LOG.error(
0886:                                    "Unable to set default property of collection object: "
0887:                                            + "\nobject: " + addLine
0888:                                            + "\nfieldName=" + fieldName
0889:                                            + "\npropertyType=" + propertyType
0890:                                            + "\nvalue=" + value, ex);
0891:                        }
0892:                    }
0893:
0894:                }
0895:                return addLine;
0896:            }
0897:
0898:            /**
0899:             * 
0900:             * @see org.kuali.core.maintenance.Maintainable#populateNewCollectionLines(java.util.Map)
0901:             */
0902:            public Map populateNewCollectionLines(Map fieldValues) {
0903:                if (LOG.isDebugEnabled()) {
0904:                    LOG.debug("populateNewCollectionLines: " + fieldValues);
0905:                }
0906:                Map cachedValues = new HashMap();
0907:
0908:                // loop over all collections with an enabled add line
0909:                List<MaintainableCollectionDefinition> collections = KNSServiceLocator
0910:                        .getMaintenanceDocumentDictionaryService()
0911:                        .getMaintainableCollections(docTypeName);
0912:
0913:                for (MaintainableCollectionDefinition coll : collections) {
0914:                    // get the collection name
0915:                    String collName = coll.getName();
0916:                    if (LOG.isDebugEnabled()) {
0917:                        LOG.debug("checking for collection: " + collName);
0918:                    }
0919:                    // build a map for that collection
0920:                    Map<String, Object> collectionValues = new HashMap<String, Object>();
0921:                    Map<String, Object> subCollectionValues = new HashMap<String, Object>();
0922:                    // loop over the collection, extracting entries with a matching prefix
0923:                    for (Object entry : fieldValues.entrySet()) {
0924:                        String key = (String) ((Map.Entry) entry).getKey();
0925:                        if (key.startsWith(collName)) {
0926:                            String subStrKey = key
0927:                                    .substring(collName.length() + 1);
0928:                            //check for subcoll w/ '[', set collName to propername and put in correct name for collection values (i.e. strip '*[x].')
0929:                            if (key.contains("[")) {
0930:
0931:                                //collName = StringUtils.substringBeforeLast(key,"[");
0932:
0933:                                //need the whole thing if subcollection
0934:                                subCollectionValues.put(key,
0935:                                        ((Map.Entry) entry).getValue());
0936:                            } else {
0937:                                collectionValues.put(subStrKey,
0938:                                        ((Map.Entry) entry).getValue());
0939:                            }
0940:                        }
0941:                    }
0942:                    // send those values to the business object
0943:                    if (LOG.isDebugEnabled()) {
0944:                        LOG.debug("values for collection: " + collectionValues);
0945:                    }
0946:                    GlobalVariables.getErrorMap().addToErrorPath(
0947:                            RiceConstants.MAINTENANCE_ADD_PREFIX + collName);
0948:                    cachedValues.putAll(FieldUtils
0949:                            .populateBusinessObjectFromMap(
0950:                                    getNewCollectionLine(collName),
0951:                                    collectionValues,
0952:                                    RiceConstants.MAINTENANCE_ADD_PREFIX
0953:                                            + collName + "."));
0954:                    GlobalVariables.getErrorMap().removeFromErrorPath(
0955:                            RiceConstants.MAINTENANCE_ADD_PREFIX + collName);
0956:                    cachedValues.putAll(populateNewSubCollectionLines(coll,
0957:                            subCollectionValues));
0958:                }
0959:
0960:                //cachedValues.putAll( FieldUtils.populateBusinessObjectFromMap( ))
0961:                return cachedValues;
0962:            }
0963:
0964:            /* Yes, I think this could be merged with the above code - I'm 
0965:             * leaving it separate until I figure out of there are any issues which would reqire
0966:             * that it be separated.
0967:             */
0968:            protected Map populateNewSubCollectionLines(
0969:                    MaintainableCollectionDefinition parentCollection,
0970:                    Map fieldValues) {
0971:                if (LOG.isDebugEnabled()) {
0972:                    LOG.debug("populateNewSubCollectionLines: " + fieldValues);
0973:                }
0974:                Map cachedValues = new HashMap();
0975:
0976:                for (MaintainableCollectionDefinition coll : parentCollection
0977:                        .getMaintainableCollections()) {
0978:                    // get the collection name
0979:                    String collName = coll.getName();
0980:
0981:                    if (LOG.isDebugEnabled()) {
0982:                        LOG.debug("checking for sub collection: " + collName);
0983:                    }
0984:                    Map<String, String> parents = new HashMap<String, String>();
0985:                    //get parents from list
0986:                    for (Object entry : fieldValues.entrySet()) {
0987:                        String key = (String) ((Map.Entry) entry).getKey();
0988:                        if (key.contains(collName)) {
0989:                            parents.put(StringUtils.substringBefore(key, "."),
0990:                                    "");
0991:                        }
0992:                    }
0993:
0994:                    for (String parent : parents.keySet()) {
0995:                        // build a map for that collection
0996:                        Map<String, Object> collectionValues = new HashMap<String, Object>();
0997:                        // loop over the collection, extracting entries with a matching prefix
0998:                        for (Object entry : fieldValues.entrySet()) {
0999:                            String key = (String) ((Map.Entry) entry).getKey();
1000:                            if (key.contains(parent)) {
1001:                                String substr = StringUtils.substringAfterLast(
1002:                                        key, ".");
1003:                                collectionValues.put(substr,
1004:                                        ((Map.Entry) entry).getValue());
1005:                            }
1006:                        }
1007:                        // send those values to the business object
1008:                        if (LOG.isDebugEnabled()) {
1009:                            LOG.debug("values for sub collection: "
1010:                                    + collectionValues);
1011:                        }
1012:                        GlobalVariables.getErrorMap().addToErrorPath(
1013:                                RiceConstants.MAINTENANCE_ADD_PREFIX + parent
1014:                                        + "." + collName);
1015:                        cachedValues
1016:                                .putAll(FieldUtils
1017:                                        .populateBusinessObjectFromMap(
1018:                                                getNewCollectionLine(parent
1019:                                                        + "." + collName),
1020:                                                collectionValues,
1021:                                                RiceConstants.MAINTENANCE_ADD_PREFIX
1022:                                                        + parent
1023:                                                        + "."
1024:                                                        + collName + "."));
1025:                        GlobalVariables.getErrorMap().removeFromErrorPath(
1026:                                RiceConstants.MAINTENANCE_ADD_PREFIX + parent
1027:                                        + "." + collName);
1028:                    }
1029:
1030:                    cachedValues.putAll(populateNewSubCollectionLines(coll,
1031:                            fieldValues));
1032:                }
1033:
1034:                return cachedValues;
1035:            }
1036:
1037:            public Collection<String> getAffectedReferencesFromLookup(
1038:                    BusinessObject baseBO, String attributeName,
1039:                    String collectionPrefix) {
1040:                PersistenceStructureService pss = KNSServiceLocator
1041:                        .getPersistenceStructureService();
1042:                String nestedBOPrefix = "";
1043:                if (ObjectUtils.isNestedAttribute(attributeName)) {
1044:                    // if we're performing a lookup on a nested attribute, we need to use the nested BO all the way down the chain
1045:                    nestedBOPrefix = ObjectUtils
1046:                            .getNestedAttributePrefix(attributeName);
1047:
1048:                    // renormalize the base BO so that the attribute name is not nested anymore 
1049:                    Class reference = ObjectUtils.getPropertyType(baseBO,
1050:                            nestedBOPrefix, pss);
1051:                    if (!(PersistableBusinessObject.class
1052:                            .isAssignableFrom(reference))) {
1053:                        return new ArrayList<String>();
1054:                    }
1055:
1056:                    try {
1057:                        baseBO = (PersistableBusinessObject) reference
1058:                                .newInstance();
1059:                    } catch (InstantiationException e) {
1060:                        // TODO Auto-generated catch block
1061:                        e.printStackTrace();
1062:                    } catch (IllegalAccessException e) {
1063:                        // TODO Auto-generated catch block
1064:                        e.printStackTrace();
1065:                    }
1066:                    attributeName = ObjectUtils
1067:                            .getNestedAttributePrimitive(attributeName);
1068:                }
1069:
1070:                if (baseBO == null) {
1071:                    return new ArrayList<String>();
1072:                }
1073:
1074:                Map<String, Class> referenceNameToClassFromPSS = LookupUtils
1075:                        .getPrimitiveReference(baseBO, attributeName);
1076:                if (referenceNameToClassFromPSS.size() > 1) {
1077:                    LOG
1078:                            .error("LookupUtils.getPrimitiveReference return results should only have at most one element");
1079:                }
1080:
1081:                BusinessObjectMetaDataService businessObjectMetaDataService = KNSServiceLocator
1082:                        .getBusinessObjectMetaDataService();
1083:                BusinessObjectRelationship relationship = businessObjectMetaDataService
1084:                        .getBusinessObjectRelationship(baseBO, attributeName);
1085:                if (relationship == null) {
1086:                    return new ArrayList<String>();
1087:                }
1088:
1089:                Map<String, String> fkToPkMappings = relationship
1090:                        .getParentToChildReferences();
1091:
1092:                Collection<String> affectedReferences = generateAllAffectedReferences(
1093:                        baseBO.getClass(), fkToPkMappings, nestedBOPrefix,
1094:                        collectionPrefix);
1095:                if (LOG.isDebugEnabled()) {
1096:                    LOG
1097:                            .debug("References affected by a lookup on BO attribute \""
1098:                                    + collectionPrefix
1099:                                    + nestedBOPrefix
1100:                                    + "."
1101:                                    + attributeName + ": " + affectedReferences);
1102:                }
1103:
1104:                return affectedReferences;
1105:            }
1106:
1107:            protected boolean isRelationshipRefreshable(Class boClass,
1108:                    String relationshipName) {
1109:                if (KNSServiceLocator.getPersistenceStructureService()
1110:                        .isPersistable(boClass)) {
1111:                    if (KNSServiceLocator.getPersistenceStructureService()
1112:                            .hasCollection(boClass, relationshipName)) {
1113:                        return !KNSServiceLocator
1114:                                .getPersistenceStructureService()
1115:                                .isCollectionUpdatable(boClass,
1116:                                        relationshipName);
1117:                    } else if (KNSServiceLocator
1118:                            .getPersistenceStructureService().hasReference(
1119:                                    boClass, relationshipName)) {
1120:                        return !KNSServiceLocator
1121:                                .getPersistenceStructureService()
1122:                                .isReferenceUpdatable(boClass, relationshipName);
1123:                    }
1124:                    // else, assume that the relationship is defined in the DD
1125:                }
1126:
1127:                return true;
1128:            }
1129:
1130:            protected Collection<String> generateAllAffectedReferences(
1131:                    Class boClass, Map<String, String> fkToPkMappings,
1132:                    String nestedBOPrefix, String collectionPrefix) {
1133:                Set<String> allAffectedReferences = new HashSet<String>();
1134:                DataDictionaryService dataDictionaryService = KNSServiceLocator
1135:                        .getDataDictionaryService();
1136:                PersistenceStructureService pss = KNSServiceLocator
1137:                        .getPersistenceStructureService();
1138:
1139:                collectionPrefix = StringUtils.isBlank(collectionPrefix) ? ""
1140:                        : collectionPrefix;
1141:
1142:                // retrieve the attributes that are affected by a lookup on attributeName.
1143:                Collection<String> attributeReferenceFKAttributes = fkToPkMappings
1144:                        .keySet();
1145:
1146:                // a lookup on an attribute may cause other attributes to be updated (e.g. account code lookup would also affect chart code)
1147:                // build a list of all affected FK values via mapKeyFields above, and for each FK, see if there are any non-updatable references with that FK
1148:
1149:                // deal with regular simple references (<reference-descriptor>s in OJB)
1150:                for (String fkAttribute : attributeReferenceFKAttributes) {
1151:                    for (String affectedReference : pss
1152:                            .getReferencesForForeignKey(boClass, fkAttribute)
1153:                            .keySet()) {
1154:                        if (isRelationshipRefreshable(boClass,
1155:                                affectedReference)) {
1156:                            if (StringUtils.isBlank(nestedBOPrefix)) {
1157:                                allAffectedReferences.add(collectionPrefix
1158:                                        + affectedReference);
1159:                            } else {
1160:                                allAffectedReferences.add(collectionPrefix
1161:                                        + nestedBOPrefix + "."
1162:                                        + affectedReference);
1163:                            }
1164:                        }
1165:                    }
1166:                }
1167:
1168:                // now with collection references (<collection-descriptor>s in OJB)
1169:                for (String collectionName : pss.listCollectionObjectTypes(
1170:                        boClass).keySet()) {
1171:                    if (isRelationshipRefreshable(boClass, collectionName)) {
1172:                        Map<String, String> keyMappingsForCollection = pss
1173:                                .getInverseForeignKeysForCollection(boClass,
1174:                                        collectionName);
1175:                        for (String collectionForeignKey : keyMappingsForCollection
1176:                                .keySet()) {
1177:                            if (attributeReferenceFKAttributes
1178:                                    .contains(collectionForeignKey)) {
1179:                                if (StringUtils.isBlank(nestedBOPrefix)) {
1180:                                    allAffectedReferences.add(collectionPrefix
1181:                                            + collectionName);
1182:                                } else {
1183:                                    allAffectedReferences.add(collectionPrefix
1184:                                            + nestedBOPrefix + "."
1185:                                            + collectionName);
1186:                                }
1187:                            }
1188:                        }
1189:                    }
1190:                }
1191:
1192:                // now use the DD to compute more affected references
1193:                List<String> ddDefinedRelationships = dataDictionaryService
1194:                        .getRelationshipNames(boClass.getName());
1195:                for (String ddRelationship : ddDefinedRelationships) {
1196:                    // note that this map is PK (key/target) => FK (value/source)
1197:                    Map<String, String> referencePKtoFKmappings = dataDictionaryService
1198:                            .getRelationshipAttributeMap(boClass.getName(),
1199:                                    ddRelationship);
1200:                    for (String sourceAttribute : referencePKtoFKmappings
1201:                            .values()) {
1202:                        // the sourceAttribute is the FK pointing to the target attribute (PK)
1203:                        if (attributeReferenceFKAttributes
1204:                                .contains(sourceAttribute)) {
1205:                            for (String affectedReference : dataDictionaryService
1206:                                    .getRelationshipEntriesForSourceAttribute(
1207:                                            boClass.getName(), sourceAttribute)) {
1208:                                if (isRelationshipRefreshable(boClass,
1209:                                        ddRelationship)) {
1210:                                    if (StringUtils.isBlank(nestedBOPrefix)) {
1211:                                        allAffectedReferences
1212:                                                .add(affectedReference);
1213:                                    } else {
1214:                                        allAffectedReferences
1215:                                                .add(nestedBOPrefix + "."
1216:                                                        + affectedReference);
1217:                                    }
1218:                                }
1219:                            }
1220:                        }
1221:                    }
1222:                }
1223:                return allAffectedReferences;
1224:            }
1225:
1226:            protected Collection<String> getAllRefreshableReferences(
1227:                    Class boClass) {
1228:                HashSet<String> references = new HashSet<String>();
1229:                for (String referenceName : KNSServiceLocator
1230:                        .getPersistenceStructureService()
1231:                        .listReferenceObjectFields(boClass).keySet()) {
1232:                    if (isRelationshipRefreshable(boClass, referenceName)) {
1233:                        references.add(referenceName);
1234:                    }
1235:                }
1236:                for (String collectionName : KNSServiceLocator
1237:                        .getPersistenceStructureService()
1238:                        .listCollectionObjectTypes(boClass).keySet()) {
1239:                    if (isRelationshipRefreshable(boClass, collectionName)) {
1240:                        references.add(collectionName);
1241:                    }
1242:                }
1243:                for (String relationshipName : KNSServiceLocator
1244:                        .getDataDictionaryService().getRelationshipNames(
1245:                                boClass.getName())) {
1246:                    if (isRelationshipRefreshable(boClass, relationshipName)) {
1247:                        references.add(relationshipName);
1248:                    }
1249:                }
1250:                return references;
1251:            }
1252:
1253:            public void handleRouteStatusChange(DocumentHeader documentHeader) {
1254:            }
1255:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.