001 /** 002 * Copyright 2005-2012 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 */ 016 package org.kuali.rice.krad.service.impl; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.core.api.mo.common.active.MutableInactivatable; 020 import org.kuali.rice.krad.bo.BusinessObject; 021 import org.kuali.rice.krad.bo.DataObjectRelationship; 022 import org.kuali.rice.krad.datadictionary.InactivationBlockingMetadata; 023 import org.kuali.rice.krad.service.BusinessObjectService; 024 import org.kuali.rice.krad.service.DataObjectMetaDataService; 025 import org.kuali.rice.krad.service.InactivationBlockingDetectionService; 026 import org.kuali.rice.krad.util.ObjectUtils; 027 import org.springframework.transaction.annotation.Transactional; 028 029 import java.util.ArrayList; 030 import java.util.Collection; 031 import java.util.HashMap; 032 import java.util.Iterator; 033 import java.util.Map; 034 035 /** 036 * Performs checking of inactivation blocking 037 * 038 * @author Kuali Rice Team (rice.collab@kuali.org) 039 */ 040 @Transactional 041 public class InactivationBlockingDetectionServiceImpl implements InactivationBlockingDetectionService { 042 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(InactivationBlockingDetectionServiceImpl.class); 043 044 protected DataObjectMetaDataService dataObjectMetaDataService; 045 protected BusinessObjectService businessObjectService; 046 047 /** 048 * Note we are checking the active getting after retrieving potential blocking records instead of setting criteria on the 049 * active field. This is because some implementations of {@link org.kuali.rice.core.api.mo.common.active.MutableInactivatable} might not have the active field, for example 050 * instances of {@link org.kuali.rice.krad.bo.InactivatableFromTo} 051 * 052 * @see org.kuali.rice.krad.service.InactivationBlockingDetectionService#listAllBlockerRecords(org.kuali.rice.krad.datadictionary.InactivationBlockingDefinition) 053 * @see org.kuali.rice.core.api.mo.common.active.MutableInactivatable 054 */ 055 @SuppressWarnings("unchecked") 056 public Collection<BusinessObject> listAllBlockerRecords(BusinessObject blockedBo, InactivationBlockingMetadata inactivationBlockingMetadata) { 057 Collection<BusinessObject> blockingRecords = new ArrayList<BusinessObject>(); 058 059 Map<String, String> queryMap = buildInactivationBlockerQueryMap(blockedBo, inactivationBlockingMetadata); 060 if (LOG.isDebugEnabled()) { 061 LOG.debug("Checking for blocker records for object: " + blockedBo); 062 LOG.debug(" With Metadata: " + inactivationBlockingMetadata); 063 LOG.debug(" Resulting Query Map: " + queryMap); 064 } 065 066 if (queryMap != null) { 067 Collection potentialBlockingRecords = businessObjectService.findMatching( 068 inactivationBlockingMetadata.getBlockingReferenceBusinessObjectClass(), queryMap); 069 for (Iterator iterator = potentialBlockingRecords.iterator(); iterator.hasNext();) { 070 MutableInactivatable businessObject = (MutableInactivatable) iterator.next(); 071 if (businessObject.isActive()) { 072 blockingRecords.add((BusinessObject) businessObject); 073 } 074 } 075 } 076 077 return blockingRecords; 078 } 079 080 /** 081 * Note we are checking the active getting after retrieving potential blocking records instead of setting criteria on the 082 * active field. This is because some implementations of {@link org.kuali.rice.core.api.mo.common.active.MutableInactivatable} might not have the active field, for example 083 * instances of {@link org.kuali.rice.krad.bo.InactivatableFromTo} 084 * 085 * @see org.kuali.rice.krad.service.InactivationBlockingDetectionService#hasABlockingRecord(org.kuali.rice.krad.bo.BusinessObject, 086 * org.kuali.rice.krad.datadictionary.InactivationBlockingMetadata) 087 * @see org.kuali.rice.core.api.mo.common.active.MutableInactivatable 088 */ 089 public boolean hasABlockingRecord(BusinessObject blockedBo, InactivationBlockingMetadata inactivationBlockingMetadata) { 090 boolean hasBlockingRecord = false; 091 092 Map<String, String> queryMap = buildInactivationBlockerQueryMap(blockedBo, inactivationBlockingMetadata); 093 if (queryMap != null) { 094 Collection potentialBlockingRecords = businessObjectService.findMatching( 095 inactivationBlockingMetadata.getBlockingReferenceBusinessObjectClass(), queryMap); 096 for (Iterator iterator = potentialBlockingRecords.iterator(); iterator.hasNext();) { 097 MutableInactivatable businessObject = (MutableInactivatable) iterator.next(); 098 if (businessObject.isActive()) { 099 hasBlockingRecord = true; 100 break; 101 } 102 } 103 } 104 105 // if queryMap were null, means that we couldn't perform a query, and hence, need to return false 106 return hasBlockingRecord; 107 } 108 109 protected Map<String, String> buildInactivationBlockerQueryMap(BusinessObject blockedBo, InactivationBlockingMetadata inactivationBlockingMetadata) { 110 BusinessObject blockingBo = (BusinessObject) ObjectUtils.createNewObjectFromClass(inactivationBlockingMetadata 111 .getBlockingReferenceBusinessObjectClass()); 112 113 DataObjectRelationship dataObjectRelationship = dataObjectMetaDataService 114 .getDataObjectRelationship(blockingBo, blockedBo.getClass(), 115 inactivationBlockingMetadata.getBlockedReferencePropertyName(), "", true, false, false); 116 117 // note, this method assumes that all PK fields of the blockedBo have a non-null and, for strings, non-blank values 118 if (dataObjectRelationship != null) { 119 Map<String, String> parentToChildReferences = dataObjectRelationship.getParentToChildReferences(); 120 Map<String, String> queryMap = new HashMap<String, String>(); 121 for (Map.Entry<String, String> parentToChildReference : parentToChildReferences.entrySet()) { 122 String fieldName = parentToChildReference.getKey(); 123 Object fieldValue = ObjectUtils.getPropertyValue(blockedBo, parentToChildReference.getValue()); 124 if (fieldValue != null && StringUtils.isNotBlank(fieldValue.toString())) { 125 queryMap.put(fieldName, fieldValue.toString()); 126 } else { 127 LOG.error("Found null value for foreign key field " + fieldName 128 + " while building inactivation blocking query map."); 129 throw new RuntimeException("Found null value for foreign key field '" + fieldName 130 + "' while building inactivation blocking query map."); 131 } 132 } 133 134 return queryMap; 135 } 136 137 return null; 138 } 139 140 public void setDataObjectMetaDataService(DataObjectMetaDataService dataObjectMetaDataService) { 141 this.dataObjectMetaDataService = dataObjectMetaDataService; 142 } 143 144 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 145 this.businessObjectService = businessObjectService; 146 } 147 148 }