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.krms.impl.ui;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException;
20  import org.kuali.rice.core.api.uif.RemotableAttributeField;
21  import org.kuali.rice.krad.bo.PersistableBusinessObject;
22  import org.kuali.rice.krad.document.MaintenanceDocument;
23  import org.kuali.rice.krad.maintenance.Maintainable;
24  import org.kuali.rice.krad.maintenance.MaintainableImpl;
25  import org.kuali.rice.krad.service.BusinessObjectService;
26  import org.kuali.rice.krad.service.KRADServiceLocator;
27  import org.kuali.rice.krad.uif.container.CollectionGroup;
28  import org.kuali.rice.krad.uif.container.Container;
29  import org.kuali.rice.krad.uif.view.View;
30  import org.kuali.rice.krad.util.KRADConstants;
31  import org.kuali.rice.krad.web.form.MaintenanceForm;
32  import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
33  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
34  import org.kuali.rice.krms.framework.type.ActionTypeService;
35  import org.kuali.rice.krms.framework.type.AgendaTypeService;
36  import org.kuali.rice.krms.framework.type.RuleTypeService;
37  import org.kuali.rice.krms.impl.repository.ActionBo;
38  import org.kuali.rice.krms.impl.repository.AgendaBo;
39  import org.kuali.rice.krms.impl.repository.ContextBoService;
40  import org.kuali.rice.krms.impl.repository.KrmsAttributeDefinitionService;
41  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
42  import org.kuali.rice.krms.impl.type.ActionTypeServiceBase;
43  import org.kuali.rice.krms.impl.type.AgendaTypeServiceBase;
44  import org.kuali.rice.krms.impl.type.RuleTypeServiceBase;
45  
46  import java.util.ArrayList;
47  import java.util.HashMap;
48  import java.util.List;
49  import java.util.Map;
50  
51  /**
52   * {@link Maintainable} for the {@link AgendaEditor}
53   * 
54   * @author Kuali Rice Team (rice.collab@kuali.org)
55   *
56   */
57  public class AgendaEditorMaintainable extends MaintainableImpl {
58  	
59  	private static final long serialVersionUID = 1L;
60  
61      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AgendaEditorMaintainable.class);
62  
63  	/**
64  	 * @return the boService
65  	 */
66  	public BusinessObjectService getBoService() {
67  		return KRADServiceLocator.getBusinessObjectService();
68  	}
69  
70      /**
71       * return the contextBoService
72       */
73      private ContextBoService getContextBoService() {
74          return KrmsRepositoryServiceLocator.getContextBoService();
75      }
76  
77      public List<RemotableAttributeField> retrieveCustomAttributes(View view, Object model, Container container) {
78          List<RemotableAttributeField> results = new ArrayList<RemotableAttributeField>();
79  
80          MaintenanceForm maintenanceForm = (MaintenanceForm)model;
81          AgendaEditor agendaEditor = (AgendaEditor)maintenanceForm.getDocument().getNewMaintainableObject().getDataObject();
82  
83          // if we have an agenda w/ a typeId set on it
84          if (agendaEditor.getAgenda() != null && !StringUtils.isBlank(agendaEditor.getAgenda().getTypeId())) {
85  
86              String krmsTypeId = agendaEditor.getAgenda().getTypeId();
87  
88              AgendaTypeService agendaTypeService = getAgendaTypeService(krmsTypeId);
89              results.addAll(agendaTypeService.getAttributeFields(krmsTypeId));
90          }
91  
92          return results;
93      }
94  
95      private AgendaTypeService getAgendaTypeService(String krmsTypeId) {
96          //
97          // Get the AgendaTypeService by hook or by crook
98          //
99  
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 }