001/** 002 * Copyright 2005-2015 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kns.maintenance; 017 018import org.kuali.rice.kns.service.KNSServiceLocator; 019import org.kuali.rice.kns.bo.GlobalBusinessObject; 020import org.kuali.rice.kns.bo.GlobalBusinessObjectDetail; 021import org.kuali.rice.krad.bo.PersistableBusinessObject; 022import org.kuali.rice.krad.data.KradDataServiceLocator; 023import org.kuali.rice.krad.data.MaterializeOption; 024import org.kuali.rice.krad.maintenance.MaintenanceLock; 025import org.kuali.rice.krad.service.BusinessObjectService; 026import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 027import org.kuali.rice.krad.util.KRADPropertyConstants; 028import org.kuali.rice.krad.util.ObjectUtils; 029 030import java.util.HashMap; 031import java.util.List; 032import java.util.Map; 033 034/** 035 * @deprecated Only used in KNS classes, use KRAD. 036 */ 037@Deprecated 038public abstract class KualiGlobalMaintainableImpl extends KualiMaintainableImpl { 039 private static final long serialVersionUID = 4814145799502207182L; 040 041 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiGlobalMaintainableImpl.class); 042 043 /** 044 * @see org.kuali.rice.krad.maintenance.Maintainable#prepareForSave() 045 */ 046 @Override 047 public void prepareForSave() { 048 if (businessObject != null) { 049 prepareGlobalsForSave(); 050 } 051 } 052 053 /** 054 * @see org.kuali.rice.krad.maintenance.Maintainable#processAfterRetrieve() 055 */ 056 @Override 057 public void processAfterRetrieve() { 058 if (businessObject != null) { 059 processGlobalsAfterRetrieve(); 060 } 061 } 062 063 /** 064 * This method does special-case handling for Globals, doing various tasks that need to be done to make a global doc valid after 065 * its been loaded from the db/maintenance-system. 066 */ 067 protected void processGlobalsAfterRetrieve() { 068 069 // TODO: this needs refactoring ... its kind of lame that we have this set of 070 // compound list statements, this should all be refactored. This could be moved 071 // into a method on all GBOs, like GBO.prepareForSave(), or even better, subclass 072 // KualiGlobalMaintainableImpl for each global, since this is all 073 // maintainable-related stuff. 074 075 GlobalBusinessObject gbo = (GlobalBusinessObject) businessObject; 076 Class gboClass = businessObject.getClass(); 077 String finDocNumber = gbo.getDocumentNumber(); 078 079 // TODO: remove this whole pseudo-assertion code block once this gets moved into a doc-specific 080 // maintainableImpl class. 081 082 // This whole mess is to fail-fast if my assumptions about the nature of the parent bo of all 083 // global-maintenance-documents is wrong 084 boolean assumptionIsWrong = false; 085 //TODO: Revisit this. Changing since getPrimaryKeys and listPrimaryKeyFieldNames are apparently same. 086 //May be we might want to replace listPrimaryKeyFieldNames with getPrimaryKeys... Not sure. 087 List primaryKeys = KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(gboClass); 088 if (primaryKeys == null) { 089 assumptionIsWrong = true; 090 } 091 else if (primaryKeys.isEmpty()) { 092 assumptionIsWrong = true; 093 } 094 else if (primaryKeys.size() != 1) { 095 assumptionIsWrong = true; 096 } 097 else if (!primaryKeys.get(0).getClass().equals(String.class)) { 098 assumptionIsWrong = true; 099 } 100 else if (!KRADPropertyConstants.DOCUMENT_NUMBER.equalsIgnoreCase((String) primaryKeys.get(0))) { 101 assumptionIsWrong = true; 102 } 103 if (assumptionIsWrong) { 104 throw new RuntimeException("An assertion about the nature of the primary keys for this GBO has " + "failed, and processing cannot continue."); 105 } 106 107 // ASSUMPTION: This next section assumes that all GBOs have documentNumber as 108 // their only primary key field, and that its named as follows. This will 109 // either fail loudly or break silently if this assumption is not true. Once we 110 // move this sort of thing into the global-doc-specific subclasses of 111 // KualiGlobalMaintainableImpl, this will simplify tremendously. 112 Map pkMap = new HashMap(); 113 pkMap.put(KRADPropertyConstants.DOCUMENT_NUMBER, finDocNumber); 114 Object newBo = KNSServiceLocator.getBusinessObjectService().findByPrimaryKey(gboClass, pkMap); 115 if (newBo == null) { 116 throw new RuntimeException("The Global Business Object could not be retrieved from the DB. " + "This should never happen under normal circumstances. If this is a legitimate case " + "Then this exception should be removed."); 117 } 118 119 // property newCollectionRecord of PersistableObjectBase is not persisted, but is always true for globals 120 try { 121 // This was the only remaining use of this method, as the operation with the wrapper 122 // below is not necessarily safe to use in all situations, I am calling it here 123 // from within the document code where we know it's safe: 124 125 KradDataServiceLocator.getDataObjectService().wrap(businessObject).materializeReferencedObjectsToDepth(2 126 , MaterializeOption.COLLECTIONS, MaterializeOption.UPDATE_UPDATABLE_REFS); 127 128 KRADServiceLocatorWeb.getLegacyDataAdapter().setObjectPropertyDeep(businessObject, KRADPropertyConstants.NEW_COLLECTION_RECORD, 129 boolean.class, true); 130 //ObjectUtils.setObjectPropertyDeep(newBo, KRADPropertyConstants.NEW_COLLECTION_RECORD, boolean.class, true, 2); 131 } 132 catch (Exception e) { 133 LOG.error("unable to set newCollectionRecord property: " + e.getMessage()); 134 throw new RuntimeException("unable to set newCollectionRecord property: " + e.getMessage()); 135 } 136 137 // replace the GBO loaded from XML with the GBO loaded from the DB 138 setDataObject(newBo); 139 } 140 141 /** 142 * This method does special-case handling for Globals, filling out various fields that need to be filled, etc. 143 */ 144 protected void prepareGlobalsForSave() { 145 GlobalBusinessObject gbo = (GlobalBusinessObject) businessObject; 146 147 // set the documentNumber for all 148 gbo.setDocumentNumber(getDocumentNumber()); 149 150 List<? extends GlobalBusinessObjectDetail> details = gbo.getAllDetailObjects(); 151 for ( GlobalBusinessObjectDetail detail : details ) { 152 detail.setDocumentNumber(getDocumentNumber()); 153 } 154 } 155 156 /** 157 * This overrides the standard version in KualiMaintainableImpl which works for non-global maintenance documents 158 * Each global document must in turn override this with its own locking representation, since it varies from document to document (some have one detail class and others have two, and the way to combine the two detail classes is unique to document with two detail classes) 159 * @see org.kuali.rice.krad.maintenance.Maintainable#generateMaintenanceLocks() 160 */ 161 @Override 162 public abstract List<MaintenanceLock> generateMaintenanceLocks(); 163 164 /** 165 * @see org.kuali.rice.krad.maintenance.Maintainable#saveBusinessObject() 166 */ 167 @SuppressWarnings({ "rawtypes", "unchecked" }) 168 @Override 169 public void saveBusinessObject() { 170 BusinessObjectService boService = KNSServiceLocator.getBusinessObjectService(); 171 GlobalBusinessObject gbo = (GlobalBusinessObject) businessObject; 172 173 // delete any indicated BOs 174 List bosToDeactivate = gbo.generateDeactivationsToPersist(); 175 if (bosToDeactivate != null) { 176 if (!bosToDeactivate.isEmpty()) { 177 boService.save(bosToDeactivate); 178 } 179 } 180 181 // persist any indicated BOs 182 List bosToPersist = gbo.generateGlobalChangesToPersist(); 183 if (bosToPersist != null) { 184 if (!bosToPersist.isEmpty()) { 185 boService.save(bosToPersist); 186 } 187 } 188 189 } 190 191 public abstract Class<? extends PersistableBusinessObject> getPrimaryEditedBusinessObjectClass(); 192}