001 /**
002 * Copyright 2005-2013 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 }