View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.service.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.mo.common.active.MutableInactivatable;
20  import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
21  import org.kuali.rice.krad.bo.BusinessObject;
22  import org.kuali.rice.krad.bo.DataObjectRelationship;
23  import org.kuali.rice.krad.datadictionary.InactivationBlockingMetadata;
24  import org.kuali.rice.krad.service.BusinessObjectService;
25  import org.kuali.rice.krad.service.InactivationBlockingDetectionService;
26  import org.kuali.rice.krad.util.ObjectUtils;
27  import org.springframework.transaction.annotation.Transactional;
28  
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.HashMap;
32  import java.util.Iterator;
33  import java.util.Map;
34  
35  /**
36   * Performs checking of inactivation blocking 
37   * 
38   * @author Kuali Rice Team (rice.collab@kuali.org)
39   */
40  @Transactional
41  public class InactivationBlockingDetectionServiceImpl implements InactivationBlockingDetectionService {
42      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(InactivationBlockingDetectionServiceImpl.class);
43  
44      protected BusinessObjectMetaDataService businessObjectMetaDataService;
45      protected BusinessObjectService businessObjectService;
46      
47      /**
48       * Note we are checking the active getting after retrieving potential blocking records instead of setting criteria on the
49  	 * 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
50  	 * instances of {@link InactivateableFromTo}
51  	 * 
52       * @see org.kuali.rice.krad.service.InactivationBlockingDetectionService#listAllBlockerRecords(org.kuali.rice.krad.datadictionary.InactivationBlockingDefinition)
53       * @see org.kuali.rice.core.api.mo.common.active.MutableInactivatable
54       */
55      @SuppressWarnings("unchecked")
56  	public Collection<BusinessObject> listAllBlockerRecords(BusinessObject blockedBo, InactivationBlockingMetadata inactivationBlockingMetadata) {
57  		Collection<BusinessObject> blockingRecords = new ArrayList<BusinessObject>();
58  
59  		Map<String, String> queryMap = buildInactivationBlockerQueryMap(blockedBo, inactivationBlockingMetadata);
60  		if (LOG.isDebugEnabled()) {
61  			LOG.debug("Checking for blocker records for object: " + blockedBo);
62  			LOG.debug("    With Metadata: " + inactivationBlockingMetadata);
63  			LOG.debug("    Resulting Query Map: " + queryMap);
64  		}
65  
66  		if (queryMap != null) {
67  			Collection potentialBlockingRecords = businessObjectService.findMatching(
68  					inactivationBlockingMetadata.getBlockingReferenceBusinessObjectClass(), queryMap);
69  			for (Iterator iterator = potentialBlockingRecords.iterator(); iterator.hasNext();) {
70  				MutableInactivatable businessObject = (MutableInactivatable) iterator.next();
71  				if (businessObject.isActive()) {
72  					blockingRecords.add((BusinessObject) businessObject);
73  				}
74  			}
75  		}
76  
77  		return blockingRecords;
78  	}
79  
80  	/**
81  	 * Note we are checking the active getting after retrieving potential blocking records instead of setting criteria on the
82  	 * 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
83  	 * instances of {@link InactivateableFromTo}
84  	 * 
85  	 * @see org.kuali.rice.krad.service.InactivationBlockingDetectionService#hasABlockingRecord(org.kuali.rice.krad.bo.BusinessObject,
86  	 *      org.kuali.rice.krad.datadictionary.InactivationBlockingMetadata)
87  	 * @see org.kuali.rice.core.api.mo.common.active.MutableInactivatable
88  	 */
89  	public boolean hasABlockingRecord(BusinessObject blockedBo, InactivationBlockingMetadata inactivationBlockingMetadata) {
90  		boolean hasBlockingRecord = false;
91  
92  		Map<String, String> queryMap = buildInactivationBlockerQueryMap(blockedBo, inactivationBlockingMetadata);
93  		if (queryMap != null) {
94  			Collection potentialBlockingRecords = businessObjectService.findMatching(
95  					inactivationBlockingMetadata.getBlockingReferenceBusinessObjectClass(), queryMap);
96  			for (Iterator iterator = potentialBlockingRecords.iterator(); iterator.hasNext();) {
97  				MutableInactivatable businessObject = (MutableInactivatable) iterator.next();
98  				if (businessObject.isActive()) {
99  					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 = businessObjectMetaDataService
114 				.getBusinessObjectRelationship(blockingBo,
115 						inactivationBlockingMetadata.getBlockedReferencePropertyName());
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 setBusinessObjectMetaDataService(BusinessObjectMetaDataService businessObjectMetaDataService) {
141         this.businessObjectMetaDataService = businessObjectMetaDataService;
142     }
143 
144     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
145         this.businessObjectService = businessObjectService;
146     }
147 
148 }