001 /*
002 * Copyright 2011 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.kfs.module.cam.document.service.impl;
017
018 import java.util.HashMap;
019 import java.util.List;
020 import java.util.Map;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.kuali.kfs.module.cam.CamsConstants;
024 import org.kuali.kfs.module.cam.CamsKeyConstants;
025 import org.kuali.kfs.module.cam.CamsPropertyConstants.AssetTransferDocument;
026 import org.kuali.kfs.module.cam.businessobject.Asset;
027 import org.kuali.kfs.module.cam.businessobject.AssetLocation;
028 import org.kuali.kfs.module.cam.businessobject.AssetType;
029 import org.kuali.kfs.module.cam.document.service.AssetLocationService;
030 import org.kuali.kfs.sys.KFSConstants;
031 import org.kuali.kfs.sys.KFSPropertyConstants;
032 import org.kuali.kfs.sys.context.SpringContext;
033 import org.kuali.rice.kns.bo.BusinessObject;
034 import org.kuali.rice.kns.bo.State;
035 import org.kuali.rice.kns.datadictionary.DataDictionaryEntryBase;
036 import org.kuali.rice.kns.document.DocumentBase;
037 import org.kuali.rice.kns.service.BusinessObjectService;
038 import org.kuali.rice.kns.service.DataDictionaryService;
039 import org.kuali.rice.kns.service.StateService;
040 import org.kuali.rice.kns.util.GlobalVariables;
041 import org.kuali.rice.kns.util.ObjectUtils;
042
043 public class AssetLocationServiceImpl implements AssetLocationService {
044 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AssetLocationService.class);
045
046 private BusinessObjectService businessObjectService;
047 private DataDictionaryService DataDictionaryService;
048
049 /**
050 * @see org.kuali.kfs.module.cam.document.service.AssetLocationService#setOffCampusLocation(org.kuali.kfs.module.cam.businessobject.Asset)
051 */
052 public void setOffCampusLocation(Asset asset) {
053 List<AssetLocation> assetLocations = asset.getAssetLocations();
054 AssetLocation offCampusLocation = null;
055
056 for (AssetLocation location : assetLocations) {
057 if (CamsConstants.AssetLocationTypeCode.OFF_CAMPUS.equalsIgnoreCase(location.getAssetLocationTypeCode())) {
058 // We need a new instance for asset location. Otherwise, if we copy it from the assetLocations collection, it could
059 // have newBO and oldBO pointing to the same AssetLocation instance which is bad.
060 offCampusLocation = new AssetLocation(location);
061 break;
062 }
063 }
064
065 if (ObjectUtils.isNull(offCampusLocation)) {
066 offCampusLocation = new AssetLocation(asset.getCapitalAssetNumber());
067 offCampusLocation.setAssetLocationTypeCode(CamsConstants.AssetLocationTypeCode.OFF_CAMPUS);
068 }
069 asset.setOffCampusLocation(offCampusLocation);
070 }
071
072 /**
073 * update existing offCampusLocation
074 *
075 * @see org.kuali.kfs.module.cam.document.service.AssetLocationService#updateOffCampusLocation(org.kuali.kfs.module.cam.businessobject.Asset)
076 */
077 public void updateOffCampusLocation(Asset asset) {
078 AssetLocation offLocation = asset.getOffCampusLocation();
079 boolean isOffCampusEmpty = isOffCampusLocationEmpty(offLocation);
080 AssetLocation removableOffCampusLocation = null;
081
082 for (AssetLocation location : asset.getAssetLocations()) {
083 if (CamsConstants.AssetLocationTypeCode.OFF_CAMPUS.equalsIgnoreCase(location.getAssetLocationTypeCode())) {
084 if (isOffCampusEmpty) {
085 removableOffCampusLocation = location;
086 }
087 else {
088 location.setAssetLocationCityName(offLocation.getAssetLocationCityName());
089 location.setAssetLocationContactIdentifier(offLocation.getAssetLocationContactIdentifier());
090 location.setAssetLocationContactName(offLocation.getAssetLocationContactName());
091 location.setAssetLocationCountryCode(offLocation.getAssetLocationCountryCode());
092 location.setAssetLocationInstitutionName(offLocation.getAssetLocationInstitutionName());
093 location.setAssetLocationPhoneNumber(offLocation.getAssetLocationPhoneNumber());
094 location.setAssetLocationStateCode(offLocation.getAssetLocationStateCode());
095 location.setAssetLocationStreetAddress(offLocation.getAssetLocationStreetAddress());
096 location.setAssetLocationZipCode(offLocation.getAssetLocationZipCode());
097 return;
098 }
099 }
100 }
101
102 if (removableOffCampusLocation != null) {
103 asset.getAssetLocations().remove(removableOffCampusLocation);
104 }
105 else if (!isOffCampusEmpty) { // add the check for off-campus empty
106 // new offCampusLocation, add it into assetLocation List
107 asset.getAssetLocations().add(offLocation);
108 }
109
110 }
111
112 /**
113 * @see org.kuali.kfs.module.cam.document.service.AssetLocationService#isOffCampusLocationExists(org.kuali.kfs.module.cam.businessobject.AssetLocation)
114 */
115 public boolean isOffCampusLocationExists(AssetLocation offCampusLocation) {
116 if (ObjectUtils.isNotNull(offCampusLocation)) {
117 if (CamsConstants.AssetLocationTypeCode.OFF_CAMPUS.equalsIgnoreCase(offCampusLocation.getAssetLocationTypeCode())) {
118 return true;
119 }
120 }
121 return false;
122 }
123
124 /**
125 * @see org.kuali.kfs.module.cam.document.service.AssetLocationService#isOffCampusLocationEmpty(org.kuali.kfs.module.cam.businessobject.AssetLocation)
126 */
127 public boolean isOffCampusLocationEmpty(AssetLocation offCampusLocation) {
128 if (ObjectUtils.isNotNull(offCampusLocation)) {
129 if (StringUtils.isNotBlank(offCampusLocation.getAssetLocationCityName()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationContactIdentifier()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationContactName()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationCountryCode()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationInstitutionName()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationPhoneNumber()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationStateCode()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationStreetAddress()) || StringUtils.isNotBlank(offCampusLocation.getAssetLocationZipCode())) {
130 return false;
131 }
132 }
133 return true;
134 }
135
136 /**
137 * @see org.kuali.kfs.module.cam.document.service.AssetLocationService#validateLocation(java.lang.Object,
138 * org.kuali.kfs.module.cam.businessobject.Asset, java.util.Map)
139 */
140 public boolean validateLocation(Map<LocationField, String> fieldMap, BusinessObject businessObject, boolean isCapital, AssetType assetType) {
141 String campusCode = readPropertyValue(businessObject, fieldMap, LocationField.CAMPUS_CODE);
142 String buildingCode = readPropertyValue(businessObject, fieldMap, LocationField.BUILDING_CODE);
143 String roomNumber = readPropertyValue(businessObject, fieldMap, LocationField.ROOM_NUMBER);
144 String subRoomNumber = readPropertyValue(businessObject, fieldMap, LocationField.SUB_ROOM_NUMBER);
145 String contactName = readPropertyValue(businessObject, fieldMap, LocationField.CONTACT_NAME);
146 String streetAddress = readPropertyValue(businessObject, fieldMap, LocationField.STREET_ADDRESS);
147 String cityName = readPropertyValue(businessObject, fieldMap, LocationField.CITY_NAME);
148 String stateCode = readPropertyValue(businessObject, fieldMap, LocationField.STATE_CODE);
149 String zipCode = readPropertyValue(businessObject, fieldMap, LocationField.ZIP_CODE);
150 String countryCode = readPropertyValue(businessObject, fieldMap, LocationField.COUNTRY_CODE);
151
152 // businessObject parameter could be BusinessObjectEntry or TransactionalDocumentEntry
153 DataDictionaryService ddService = this.getDataDictionaryService();
154 DataDictionaryEntryBase ddEntry = null;
155 if (DocumentBase.class.isAssignableFrom(businessObject.getClass())) {
156 String docTypeName = ddService.getDocumentTypeNameByClass(businessObject.getClass());
157 ddEntry = ddService.getDataDictionary().getDocumentEntry(docTypeName);
158 }
159 else {
160 ddEntry = this.getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(businessObject.getClass().getName());
161 }
162
163 boolean onCampus = StringUtils.isNotBlank(buildingCode) || StringUtils.isNotBlank(roomNumber) || StringUtils.isNotBlank(subRoomNumber);
164 boolean offCampus = StringUtils.isNotBlank(contactName) || StringUtils.isNotBlank(streetAddress) || StringUtils.isNotBlank(cityName) || StringUtils.isNotBlank(stateCode) || StringUtils.isNotBlank(zipCode) || StringUtils.isNotBlank(countryCode);
165
166 boolean valid = true;
167 if (onCampus && offCampus) {
168 putError(fieldMap, LocationField.BUILDING_CODE, CamsKeyConstants.AssetLocation.ERROR_CHOOSE_LOCATION_INFO);
169 valid &= false;
170 }
171 else {
172 if (isCapital) {
173 valid &= validateCapitalAssetLocation(assetType, fieldMap, campusCode, buildingCode, roomNumber, subRoomNumber, contactName, streetAddress, cityName, stateCode, zipCode, countryCode, onCampus, offCampus, ddEntry);
174 }
175 else {
176 valid &= validateNonCapitalAssetLocation(fieldMap, contactName, streetAddress, cityName, stateCode, zipCode, countryCode, onCampus, offCampus);
177 }
178 }
179 return valid;
180 }
181
182
183 protected boolean validateCapitalAssetLocation(AssetType assetType, Map<LocationField, String> fieldMap, String campusCode, String buildingCode, String roomNumber, String subRoomNumber, String contactName, String streetAddress, String cityName, String stateCode, String zipCode, String countryCode, boolean onCampus, boolean offCampus, DataDictionaryEntryBase businessObjectEntry) {
184 boolean valid = true;
185 if (ObjectUtils.isNull(assetType)) {
186 GlobalVariables.getMessageMap().putErrorForSectionId(CamsConstants.LOCATION_INFORMATION_SECTION_ID, CamsKeyConstants.AssetLocation.ERROR_CHOOSE_ASSET_TYPE);
187 valid &= false;
188 }
189 else {
190 String label;
191 if (assetType.isRequiredBuildingIndicator() && offCampus) {
192 // off campus information not allowed
193 if (StringUtils.isNotBlank(contactName)) {
194 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.CONTACT_NAME)).getLabel();
195 putError(fieldMap, LocationField.CONTACT_NAME, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
196 valid &= false;
197 }
198 if (StringUtils.isNotBlank(streetAddress)) {
199 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.STREET_ADDRESS)).getLabel();
200 putError(fieldMap, LocationField.STREET_ADDRESS, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
201 valid &= false;
202 }
203
204 if (StringUtils.isNotBlank(cityName)) {
205 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.CITY_NAME)).getLabel();
206 putError(fieldMap, LocationField.CITY_NAME, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
207 valid &= false;
208 }
209
210 if (StringUtils.isNotBlank(stateCode)) {
211 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.STATE_CODE)).getLabel();
212 putError(fieldMap, LocationField.STATE_CODE, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
213 valid &= false;
214 }
215
216 if (StringUtils.isNotBlank(zipCode)) {
217 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.ZIP_CODE)).getLabel();
218 putError(fieldMap, LocationField.ZIP_CODE, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
219 valid &= false;
220 }
221
222 if (StringUtils.isNotBlank(countryCode)) {
223 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.COUNTRY_CODE)).getLabel();
224 putError(fieldMap, LocationField.COUNTRY_CODE, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
225 valid &= false;
226 }
227 }
228 else if (!assetType.isMovingIndicator() && !assetType.isRequiredBuildingIndicator() && onCampus) {
229 // land information cannot have on-campus
230 if (StringUtils.isNotBlank(buildingCode)) {
231 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.BUILDING_CODE)).getLabel();
232 putError(fieldMap, LocationField.BUILDING_CODE, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
233 valid &= false;
234 }
235
236 if (StringUtils.isNotBlank(roomNumber)) {
237 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.ROOM_NUMBER)).getLabel();
238 putError(fieldMap, LocationField.ROOM_NUMBER, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
239 valid &= false;
240 }
241
242 if (StringUtils.isNotBlank(subRoomNumber)) {
243 label = businessObjectEntry.getAttributeDefinition(fieldMap.get(LocationField.SUB_ROOM_NUMBER)).getLabel();
244 putError(fieldMap, LocationField.SUB_ROOM_NUMBER, CamsKeyConstants.AssetLocation.ERROR_LOCATION_NOT_PERMITTED_ASSET_TYPE, new String[] { label, assetType.getCapitalAssetTypeDescription() });
245 valid &= false;
246 }
247 }
248 else if (onCampus) {
249 valid = validateOnCampusLocation(fieldMap, assetType, campusCode, buildingCode, roomNumber, subRoomNumber);
250 }
251 else if (offCampus) {
252 valid = validateOffCampusLocation(fieldMap, contactName, streetAddress, cityName, stateCode, zipCode, countryCode);
253 }
254 else if (assetType.isMovingIndicator() || assetType.isRequiredBuildingIndicator()) {
255 putError(fieldMap, LocationField.BUILDING_CODE, CamsKeyConstants.AssetLocation.ERROR_LOCATION_INFO_REQUIRED);
256 valid &= false;
257 }
258 }
259 return valid;
260 }
261
262 protected boolean validateNonCapitalAssetLocation(Map<LocationField, String> fieldMap, String contactName, String streetAddress, String cityName, String stateCode, String zipCode, String countryCode, boolean onCampus, boolean offCampus) {
263 boolean valid = true;
264 if (offCampus) {
265 valid = validateOffCampusLocation(fieldMap, contactName, streetAddress, cityName, stateCode, zipCode, countryCode);
266 }
267 return valid;
268 }
269
270
271 /**
272 * Convenience method to append the path prefix
273 */
274 protected void putError(Map<LocationField, String> fieldMap, LocationField field, String errorKey, String... errorParameters) {
275 GlobalVariables.getMessageMap().putError(fieldMap.get(field), errorKey, errorParameters);
276 }
277
278 protected boolean validateOnCampusLocation(Map<LocationField, String> fieldMap, AssetType assetType, String campusCode, String buildingCode, String buildingRoomNumber, String subRoomNumber) {
279 boolean valid = true;
280 if (assetType.isMovingIndicator()) {
281 if (StringUtils.isBlank(buildingCode)) {
282 putError(fieldMap, LocationField.BUILDING_CODE, CamsKeyConstants.AssetLocation.ERROR_ONCAMPUS_BUILDING_CODE_REQUIRED, assetType.getCapitalAssetTypeDescription());
283 valid &= false;
284 }
285 if (StringUtils.isBlank(buildingRoomNumber)) {
286 putError(fieldMap, LocationField.ROOM_NUMBER, CamsKeyConstants.AssetLocation.ERROR_ONCAMPUS_BUILDING_ROOM_NUMBER_REQUIRED, assetType.getCapitalAssetTypeDescription());
287 valid &= false;
288 }
289 }
290 if (assetType.isRequiredBuildingIndicator()) {
291 if (StringUtils.isBlank(buildingCode)) {
292 putError(fieldMap, LocationField.BUILDING_CODE, CamsKeyConstants.AssetLocation.ERROR_ONCAMPUS_BUILDING_CODE_REQUIRED, assetType.getCapitalAssetTypeDescription());
293 valid &= false;
294 }
295 if (StringUtils.isNotBlank(buildingRoomNumber)) {
296 putError(fieldMap, LocationField.ROOM_NUMBER, CamsKeyConstants.AssetLocation.ERROR_ONCAMPUS_BUILDING_ROOM_NUMBER_NOT_PERMITTED, assetType.getCapitalAssetTypeDescription());
297 valid &= false;
298 }
299 if (StringUtils.isNotBlank(subRoomNumber)) {
300 putError(fieldMap, LocationField.SUB_ROOM_NUMBER, CamsKeyConstants.AssetLocation.ERROR_ONCAMPUS_SUB_ROOM_NUMBER_NOT_PERMITTED, assetType.getCapitalAssetTypeDescription());
301 valid &= false;
302 }
303 }
304 return valid;
305 }
306
307 protected boolean validateOffCampusLocation(Map<LocationField, String> fieldMap, String contactName, String streetAddress, String cityName, String stateCode, String zipCode, String countryCode) {
308 boolean valid = true;
309 boolean isCountryUS = false;
310 if (isBlank(fieldMap, LocationField.COUNTRY_CODE, countryCode)) {
311 putError(fieldMap, LocationField.COUNTRY_CODE, CamsKeyConstants.AssetLocation.ERROR_OFFCAMPUS_COUNTRY_REQUIRED);
312 valid &= false;
313 }
314 else {
315 isCountryUS = countryCode.equals(KFSConstants.COUNTRY_CODE_UNITED_STATES);
316 }
317
318 if (isBlank(fieldMap, LocationField.CONTACT_NAME, contactName)) {
319 putError(fieldMap, LocationField.CONTACT_NAME, CamsKeyConstants.AssetLocation.ERROR_OFFCAMPUS_CONTACT_REQUIRED);
320 valid &= false;
321 }
322
323 if (isBlank(fieldMap, LocationField.STREET_ADDRESS, streetAddress)) {
324 putError(fieldMap, LocationField.STREET_ADDRESS, CamsKeyConstants.AssetLocation.ERROR_OFFCAMPUS_ADDRESS_REQUIRED);
325 valid &= false;
326 }
327 if (isBlank(fieldMap, LocationField.CITY_NAME, cityName)) {
328 putError(fieldMap, LocationField.CITY_NAME, CamsKeyConstants.AssetLocation.ERROR_OFFCAMPUS_CITY_REQUIRED);
329 valid &= false;
330 }
331
332
333 if (isCountryUS) {
334 if (isBlank(fieldMap, LocationField.STATE_CODE, stateCode)) {
335 putError(fieldMap, LocationField.STATE_CODE, CamsKeyConstants.AssetLocation.ERROR_OFFCAMPUS_STATE_REQUIRED);
336 valid &= false;
337 }
338 if (isBlank(fieldMap, LocationField.ZIP_CODE, zipCode)) {
339 putError(fieldMap, LocationField.ZIP_CODE, CamsKeyConstants.AssetLocation.ERROR_OFFCAMPUS_ZIP_REQUIRED);
340 valid &= false;
341 }
342 if (!isBlank(fieldMap, LocationField.STATE_CODE, stateCode)) {
343 Map assetLocationMap = new HashMap();
344 assetLocationMap.put(KFSPropertyConstants.POSTAL_STATE_CODE, stateCode);
345 State locationState = SpringContext.getBean(StateService.class).getByPrimaryId(stateCode);
346 if (ObjectUtils.isNull(locationState)) {
347 putError(fieldMap, LocationField.STATE_CODE, CamsKeyConstants.AssetLocation.ERROR_INVALID_OFF_CAMPUS_STATE, stateCode);
348 valid &= false;
349 }
350 }
351 }
352
353 return valid;
354 }
355
356 protected boolean isBlank(Map<LocationField, String> fieldMap, LocationField field, String countryCode) {
357 return fieldMap.get(field) != null && StringUtils.isBlank(countryCode);
358 }
359
360 protected String readPropertyValue(BusinessObject currObject, Map<LocationField, String> fieldMap, LocationField field) {
361 String stringValue = null;
362 try {
363 String propertyName = fieldMap.get(field);
364 if (propertyName != null) {
365 stringValue = (String) ObjectUtils.getNestedValue(currObject, propertyName);
366 }
367 }
368 catch (Exception e) {
369 throw new RuntimeException(e);
370 }
371 return stringValue;
372 }
373
374 public BusinessObjectService getBusinessObjectService() {
375 return businessObjectService;
376 }
377
378 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
379 this.businessObjectService = businessObjectService;
380 }
381
382 public DataDictionaryService getDataDictionaryService() {
383 return DataDictionaryService;
384 }
385
386 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
387 DataDictionaryService = dataDictionaryService;
388 }
389
390 }