001 /** 002 * Copyright 2005-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.rice.krms.impl.ui; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException; 020 import org.kuali.rice.core.api.uif.RemotableAttributeField; 021 import org.kuali.rice.krad.bo.PersistableBusinessObject; 022 import org.kuali.rice.krad.document.MaintenanceDocument; 023 import org.kuali.rice.krad.maintenance.Maintainable; 024 import org.kuali.rice.krad.maintenance.MaintainableImpl; 025 import org.kuali.rice.krad.service.BusinessObjectService; 026 import org.kuali.rice.krad.service.KRADServiceLocator; 027 import org.kuali.rice.krad.uif.container.CollectionGroup; 028 import org.kuali.rice.krad.uif.container.Container; 029 import org.kuali.rice.krad.uif.view.View; 030 import org.kuali.rice.krad.util.KRADConstants; 031 import org.kuali.rice.krad.web.form.MaintenanceForm; 032 import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition; 033 import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition; 034 import org.kuali.rice.krms.framework.type.ActionTypeService; 035 import org.kuali.rice.krms.framework.type.AgendaTypeService; 036 import org.kuali.rice.krms.framework.type.RuleTypeService; 037 import org.kuali.rice.krms.impl.repository.ActionBo; 038 import org.kuali.rice.krms.impl.repository.AgendaBo; 039 import org.kuali.rice.krms.impl.repository.ContextBoService; 040 import org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService; 041 import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator; 042 import org.kuali.rice.krms.impl.type.ActionTypeServiceBase; 043 import org.kuali.rice.krms.impl.type.AgendaTypeServiceBase; 044 import org.kuali.rice.krms.impl.type.RuleTypeServiceBase; 045 046 import java.util.ArrayList; 047 import java.util.HashMap; 048 import java.util.List; 049 import java.util.Map; 050 051 /** 052 * {@link Maintainable} for the {@link AgendaEditor} 053 * 054 * @author Kuali Rice Team (rice.collab@kuali.org) 055 * 056 */ 057 public class AgendaEditorMaintainable extends MaintainableImpl { 058 059 private static final long serialVersionUID = 1L; 060 061 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AgendaEditorMaintainable.class); 062 063 /** 064 * @return the boService 065 */ 066 public BusinessObjectService getBoService() { 067 return KRADServiceLocator.getBusinessObjectService(); 068 } 069 070 /** 071 * return the contextBoService 072 */ 073 private ContextBoService getContextBoService() { 074 return KrmsRepositoryServiceLocator.getContextBoService(); 075 } 076 077 public List<RemotableAttributeField> retrieveCustomAttributes(View view, Object model, Container container) { 078 List<RemotableAttributeField> results = new ArrayList<RemotableAttributeField>(); 079 080 MaintenanceForm maintenanceForm = (MaintenanceForm)model; 081 AgendaEditor agendaEditor = (AgendaEditor)maintenanceForm.getDocument().getNewMaintainableObject().getDataObject(); 082 083 // if we have an agenda w/ a typeId set on it 084 if (agendaEditor.getAgenda() != null && !StringUtils.isBlank(agendaEditor.getAgenda().getTypeId())) { 085 086 String krmsTypeId = agendaEditor.getAgenda().getTypeId(); 087 088 AgendaTypeService agendaTypeService = getAgendaTypeService(krmsTypeId); 089 results.addAll(agendaTypeService.getAttributeFields(krmsTypeId)); 090 } 091 092 return results; 093 } 094 095 private AgendaTypeService getAgendaTypeService(String krmsTypeId) { 096 // 097 // Get the AgendaTypeService by hook or by crook 098 // 099 100 KrmsTypeDefinition krmsType = 101 KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService(). 102 getTypeById(krmsTypeId); 103 104 AgendaTypeService agendaTypeService = null; 105 106 if (!StringUtils.isBlank(krmsTypeId)) { 107 String serviceName = krmsType.getServiceName(); 108 109 if (!StringUtils.isBlank(serviceName)) { 110 agendaTypeService = KrmsRepositoryServiceLocator.getService(serviceName); 111 } 112 } 113 114 if (agendaTypeService == null) { agendaTypeService = AgendaTypeServiceBase.defaultAgendaTypeService; } 115 116 return agendaTypeService; 117 } 118 119 /** 120 * This only supports a single action within a rule. 121 */ 122 public List<RemotableAttributeField> retrieveRuleActionCustomAttributes(View view, Object model, Container container) { 123 List<RemotableAttributeField> results = new ArrayList<RemotableAttributeField>(); 124 125 MaintenanceForm maintenanceForm = (MaintenanceForm)model; 126 AgendaEditor agendaEditor = (AgendaEditor)maintenanceForm.getDocument().getNewMaintainableObject().getDataObject(); 127 128 // if we have an rule action w/ a typeId set on it 129 if (!StringUtils.isBlank(agendaEditor.getAgendaItemLineRuleAction().getTypeId())) { 130 ActionTypeService actionTypeService = getActionTypeService(agendaEditor.getAgendaItemLineRuleAction().getTypeId()); 131 results.addAll(actionTypeService.getAttributeFields(agendaEditor.getAgendaItemLineRuleAction().getTypeId())); 132 } 133 134 return results; 135 } 136 137 public List<RemotableAttributeField> retrieveRuleCustomAttributes(View view, Object model, Container container) { 138 List<RemotableAttributeField> results = new ArrayList<RemotableAttributeField>(); 139 140 MaintenanceForm maintenanceForm = (MaintenanceForm)model; 141 AgendaEditor agendaEditor = (AgendaEditor)maintenanceForm.getDocument().getNewMaintainableObject().getDataObject(); 142 143 // if we have an rule w/ a typeId set on it 144 if (agendaEditor.getAgendaItemLine() != null && agendaEditor.getAgendaItemLine().getRule() != null 145 && !StringUtils.isBlank(agendaEditor.getAgendaItemLine().getRule().getTypeId())) { 146 147 String krmsTypeId = agendaEditor.getAgendaItemLine().getRule().getTypeId(); 148 149 RuleTypeService ruleTypeService = getRuleTypeService(krmsTypeId); 150 results.addAll(ruleTypeService.getAttributeFields(krmsTypeId)); 151 } 152 153 return results; 154 } 155 156 private ActionTypeService getActionTypeService(String krmsTypeId) { 157 // 158 // Get the ActionTypeService by hook or by crook 159 // 160 161 KrmsTypeDefinition krmsType = 162 KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService(). 163 getTypeById(krmsTypeId); 164 165 ActionTypeService actionTypeService = null; 166 167 if (!StringUtils.isBlank(krmsTypeId)) { 168 String serviceName = krmsType.getServiceName(); 169 170 if (!StringUtils.isBlank(serviceName)) { 171 actionTypeService = KrmsRepositoryServiceLocator.getService(serviceName); 172 } 173 } 174 if (actionTypeService == null) { 175 actionTypeService = ActionTypeServiceBase.defaultActionTypeService; 176 } 177 178 // if (actionTypeService == null) { actionTypeService = AgendaTypeServiceBase.defaultAgendaTypeService; } 179 180 return actionTypeService; 181 } 182 183 private RuleTypeService getRuleTypeService(String krmsTypeId) { 184 RuleTypeService ruleTypeService = null; 185 String serviceName = getRuleTypeServiceName(krmsTypeId); 186 187 if (!StringUtils.isBlank(serviceName)) { 188 ruleTypeService = KrmsRepositoryServiceLocator.getService(serviceName); 189 } 190 if (ruleTypeService == null) { 191 ruleTypeService = RuleTypeServiceBase.defaultRuleTypeService; 192 } 193 return ruleTypeService; 194 } 195 196 private String getRuleTypeServiceName(String krmsTypeId) { 197 String serviceName = null; 198 KrmsTypeDefinition krmsType = 199 KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService(). 200 getTypeById(krmsTypeId); 201 202 if (!StringUtils.isBlank(krmsTypeId)) { 203 serviceName = krmsType.getServiceName(); 204 } 205 return serviceName; 206 } 207 208 @Override 209 public Object retrieveObjectForEditOrCopy(MaintenanceDocument document, Map<String, String> dataObjectKeys) { 210 Object dataObject = null; 211 212 try { 213 // Since the dataObject is a wrapper class we need to build it and populate with the agenda bo. 214 AgendaEditor agendaEditor = new AgendaEditor(); 215 AgendaBo agenda = getLookupService().findObjectBySearch(((AgendaEditor) getDataObject()).getAgenda().getClass(), dataObjectKeys); 216 if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(getMaintenanceAction())) { 217 // If we don't clear the primary key and set the fieldsClearedOnCopy flag then the 218 // MaintenanceDocumentServiceImpl.processMaintenanceObjectForCopy() will try to locate the primary keys in 219 // an attempt to clear them which again would cause an exception due to the wrapper class. 220 agenda.setId(null); 221 document.setFieldsClearedOnCopy(true); 222 } 223 agendaEditor.setAgenda(agenda); 224 225 // set custom attributes map in AgendaEditor 226 agendaEditor.setCustomAttributesMap(agenda.getAttributes()); 227 228 // set extra fields on AgendaEditor 229 agendaEditor.setNamespace(agenda.getContext().getNamespace()); 230 agendaEditor.setContextName(agenda.getContext().getName()); 231 232 dataObject = agendaEditor; 233 } catch (ClassNotPersistenceCapableException ex) { 234 if (!document.getOldMaintainableObject().isExternalBusinessObject()) { 235 throw new RuntimeException("Data Object Class: " + getDataObjectClass() + 236 " is not persistable and is not externalizable - configuration error"); 237 } 238 // otherwise, let fall through 239 } 240 241 return dataObject; 242 } 243 244 /** 245 * {@inheritDoc} 246 */ 247 @Override 248 public void processAfterNew(MaintenanceDocument document, 249 Map<String, String[]> requestParameters) { 250 251 super.processAfterNew(document, requestParameters); 252 document.getDocumentHeader().setDocumentDescription("New Agenda Editor Document"); 253 254 // if (KRADConstants.MAINTENANCE_NEW_ACTION.equals(maintenanceAction)) { 255 // String[] agendaIds = requestParameters.get("agendaId"); 256 // if (agendaIds == null || agendaIds.length != 1) { 257 // //throw new RiceRuntimeException("one and only one agendaId request parameter may be passed"); 258 // } else { 259 // // TODO: change this, it makes more sense for MAINTENANCE_EDIT_ACTION 260 // String agendaId = agendaIds[0]; 261 // 262 // AgendaBo agenda = getBoService().findBySinglePrimaryKey(AgendaBo.class, agendaId); 263 // String contextId = agenda.getContextId(); 264 // 265 // ContextBo context = getBoService().findBySinglePrimaryKey(ContextBo.class, contextId); 266 // 267 // AgendaEditor editor = (AgendaEditor) document.getDocumentBusinessObject(); 268 // 269 // editor.setContext(context); 270 // editor.setAgenda(agenda); 271 // } 272 // } 273 274 275 } 276 277 @Override 278 public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> requestParameters) { 279 super.processAfterCopy(document, requestParameters); 280 document.getDocumentHeader().setDocumentDescription("New Agenda Editor Document"); 281 } 282 283 @Override 284 public void processAfterEdit(MaintenanceDocument document, Map<String, String[]> requestParameters) { 285 super.processAfterEdit(document, requestParameters); 286 document.getDocumentHeader().setDocumentDescription("Modify Agenda Editor Document"); 287 } 288 289 @Override 290 public void prepareForSave() { 291 // set agenda attributes 292 AgendaEditor agendaEditor = (AgendaEditor) getDataObject(); 293 agendaEditor.getAgenda().setAttributes(agendaEditor.getCustomAttributesMap()); 294 } 295 296 @Override 297 public void saveDataObject() { 298 AgendaBo agendaBo = ((AgendaEditor) getDataObject()).getAgenda(); 299 if (agendaBo instanceof PersistableBusinessObject) { 300 Map<String,String> primaryKeys = new HashMap<String, String>(); 301 primaryKeys.put("id", agendaBo.getId()); 302 AgendaBo blah = getBusinessObjectService().findByPrimaryKey(AgendaBo.class, primaryKeys); 303 getBusinessObjectService().delete(blah); 304 305 getBusinessObjectService().linkAndSave(agendaBo); 306 } else { 307 throw new RuntimeException( 308 "Cannot save object of type: " + agendaBo + " with business object service"); 309 } 310 } 311 312 /** 313 * Build a map from attribute name to attribute definition from all the defined attribute definitions for the 314 * specified agenda type 315 * @param agendaTypeId 316 * @return 317 */ 318 private Map<String, KrmsAttributeDefinition> buildAttributeDefinitionMap(String agendaTypeId) { 319 KrmsAttributeDefinitionService attributeDefinitionService = 320 KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService(); 321 322 // build a map from attribute name to definition 323 Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>(); 324 325 List<KrmsAttributeDefinition> attributeDefinitions = 326 attributeDefinitionService.findAttributeDefinitionsByType(agendaTypeId); 327 328 for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) { 329 attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition); 330 } 331 return attributeDefinitionMap; 332 } 333 334 @Override 335 public boolean isOldDataObjectInDocument() { 336 boolean isOldDataObjectInExistence = true; 337 338 if (getDataObject() == null) { 339 isOldDataObjectInExistence = false; 340 } else { 341 // dataObject contains a non persistable wrapper - use agenda from the wrapper object instead 342 Map<String, ?> keyFieldValues = getDataObjectMetaDataService().getPrimaryKeyFieldValues(((AgendaEditor) getDataObject()).getAgenda()); 343 for (Object keyValue : keyFieldValues.values()) { 344 if (keyValue == null) { 345 isOldDataObjectInExistence = false; 346 } else if ((keyValue instanceof String) && StringUtils.isBlank((String) keyValue)) { 347 isOldDataObjectInExistence = false; 348 } 349 350 if (!isOldDataObjectInExistence) { 351 break; 352 } 353 } 354 } 355 356 return isOldDataObjectInExistence; 357 } 358 359 // Since the dataObject is a wrapper class we need to return the agendaBo instead. 360 @Override 361 public Class getDataObjectClass() { 362 return AgendaBo.class; 363 } 364 365 @Override 366 protected void processBeforeAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) { 367 MaintenanceForm form = (MaintenanceForm) model; 368 AgendaEditor agendaEditor = (AgendaEditor) form.getDocument().getNewMaintainableObject().getDataObject(); 369 if (addLine instanceof ActionBo) { 370 ((ActionBo) addLine).setNamespace(agendaEditor.getAgendaItemLine().getRule().getNamespace()); 371 } 372 373 super.processBeforeAddLine(view, collectionGroup, model, addLine); 374 } 375 }