001 /** 002 * Copyright 2005-2012 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.kew.impl.peopleflow; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 020 import org.kuali.rice.core.api.uif.RemotableAttributeField; 021 import org.kuali.rice.kew.api.KewApiServiceLocator; 022 import org.kuali.rice.kew.api.peopleflow.PeopleFlowDefinition; 023 import org.kuali.rice.kew.api.repository.type.KewTypeDefinition; 024 import org.kuali.rice.kew.framework.peopleflow.PeopleFlowTypeService; 025 import org.kuali.rice.krad.bo.Note; 026 import org.kuali.rice.krad.maintenance.MaintainableImpl; 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.util.ObjectPropertyUtils; 030 import org.kuali.rice.krad.uif.view.View; 031 import org.kuali.rice.krad.util.KRADConstants; 032 import org.kuali.rice.krad.web.form.MaintenanceForm; 033 034 import java.util.ArrayList; 035 import java.util.Collection; 036 import java.util.Collections; 037 import java.util.Comparator; 038 import java.util.List; 039 040 /** 041 * Custom view helper for the people flow maintenance document to retrieve the type attribute remotable fields 042 * 043 * @author Kuali Rice Team (rice.collab@kuali.org) 044 */ 045 public class PeopleFlowMaintainableImpl extends MaintainableImpl { 046 047 048 /** 049 * sort {@link org.kuali.rice.kew.impl.peopleflow.PeopleFlowMemberBo}s by stop number (priority) 050 * 051 * @param collection - the Collection to add the given addLine to 052 * @param addLine - the line to add to the given collection 053 */ 054 @Override 055 protected void addLine(Collection<Object> collection, Object addLine) { 056 if (collection instanceof List) { 057 ((List) collection).add(0, addLine); 058 if (addLine instanceof PeopleFlowMemberBo) { 059 Collections.sort((List) collection, new Comparator<Object>() { 060 public int compare(Object o1, Object o2) { 061 if ((o1 instanceof PeopleFlowMemberBo) && (o1 instanceof PeopleFlowMemberBo)) { 062 return ((PeopleFlowMemberBo) o1).getPriority() - ((PeopleFlowMemberBo) o2) 063 .getPriority(); 064 } 065 return 0; // if not both PeopleFlowMemberBo something strange is going on. Use equals as doing nothing. 066 } 067 }); 068 } 069 } else { 070 collection.add(addLine); 071 } 072 } 073 074 /** 075 * Invokes the {@link org.kuali.rice.kew.api.repository.type.KewTypeRepositoryService} to retrieve the remotable 076 * field definitions for the attributes associated with the selected type 077 * 078 * @param view - view instance 079 * @param model - object containing the form data, from which the selected type will be pulled 080 * @param container - container that holds the remotable fields 081 * @return List<RemotableAttributeField> instances for the type attributes, or empty list if not attributes exist 082 */ 083 public List<RemotableAttributeField> retrieveTypeAttributes(View view, Object model, Container container) { 084 List<RemotableAttributeField> remoteFields = new ArrayList<RemotableAttributeField>(); 085 086 PeopleFlowBo peopleFlow = 087 (PeopleFlowBo) ((MaintenanceForm) model).getDocument().getNewMaintainableObject().getDataObject(); 088 089 // retrieve the type service and invoke to get the remotable field definitions 090 String typeId = peopleFlow.getTypeId(); 091 if (StringUtils.isNotBlank(typeId)) { 092 KewTypeDefinition typeDefinition = KewApiServiceLocator.getKewTypeRepositoryService().getTypeById(typeId); 093 PeopleFlowTypeService peopleFlowTypeService = GlobalResourceLoader.<PeopleFlowTypeService>getService( 094 typeDefinition.getServiceName()); 095 remoteFields = peopleFlowTypeService.getAttributeFields(typeId); 096 } 097 098 return remoteFields; 099 } 100 101 /** 102 * Set the attribute bo list from the map of attribute key/value pairs and then calls 103 * {@link org.kuali.rice.kew.api.peopleflow.PeopleFlowService} to save the people flow instance 104 */ 105 @Override 106 public void saveDataObject() { 107 ((PeopleFlowBo) getDataObject()).updateAttributeBoValues(); 108 109 PeopleFlowDefinition peopleFlowDefinition; 110 if (KRADConstants.MAINTENANCE_COPY_ACTION.equals(getMaintenanceAction())) { 111 peopleFlowDefinition = PeopleFlowBo.maintenanceCopy(((PeopleFlowBo) getDataObject())); 112 } else { 113 // this to method ends up copying a versionNumber to null versionNumber 114 peopleFlowDefinition = PeopleFlowBo.to(((PeopleFlowBo) getDataObject())); 115 } 116 if (StringUtils.isNotBlank(peopleFlowDefinition.getId())) { 117 KewApiServiceLocator.getPeopleFlowService().updatePeopleFlow(peopleFlowDefinition); 118 } else { 119 KewApiServiceLocator.getPeopleFlowService().createPeopleFlow(peopleFlowDefinition); 120 } 121 } 122 123 /** 124 * In the case of edit maintenance adds a new blank line to the old side 125 * This method is intended to override the method in MaintainableImpl 126 * but has a different set of parameters, so it is not actually an override. 127 * This version was needed to fetch the old collection from a different path 128 * than MaintainableImpl uses. 129 * 130 * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterAddLine(org.kuali.rice.krad.uif.view.View, 131 * org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object, 132 * java.lang.Object) 133 */ 134 protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine, String collectionPath) { 135 // Check for maintenance documents in edit but exclude notes 136 if (model instanceof MaintenanceForm && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceForm)model).getMaintenanceAction()) && !(addLine instanceof Note)) { 137 // MaintenanceForm maintenanceForm = (MaintenanceForm) model; 138 // MaintenanceDocument document = maintenanceForm.getDocument(); 139 140 // get the old object's collection 141 String oldCollectionPath = collectionPath.replace("newMaintainableObject","oldMaintainableObject"); 142 Collection<Object> oldCollection = ObjectPropertyUtils.getPropertyValue(model, oldCollectionPath ); 143 try { 144 Object blankLine = collectionGroup.getCollectionObjectClass().newInstance(); 145 oldCollection.add(blankLine); 146 } catch (Exception e) { 147 throw new RuntimeException("Unable to create new line instance for old maintenance object", e); 148 } 149 } 150 } 151 152 /** 153 * This method is an override of ViewHelperService.processCollectionDeleteLine(). 154 * It is virtually identical except that a local processAfterDeleteLine() method is called 155 * with a different parameter set than is called from within this method to delete the line 156 * from the old maintainable object. 157 * @see org.kuali.rice.krad.uif.service.ViewHelperService#processCollectionDeleteLine(org.kuali.rice.krad.uif.view.View, 158 * java.lang.Object, java.lang.String, int) 159 */ 160 @Override 161 public void processCollectionDeleteLine(View view, Object model, String collectionPath, int lineIndex) { 162 // get the collection group from the view 163 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath); 164 if (collectionGroup == null) { 165 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath); 166 } 167 168 // get the collection instance for adding the new line 169 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath); 170 if (collection == null) { 171 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath); 172 } 173 174 // TODO: look into other ways of identifying a line so we can deal with 175 // unordered collections 176 if (collection instanceof List) { 177 Object deleteLine = ((List<Object>) collection).get(lineIndex); 178 179 // validate the delete action is allowed for this line 180 boolean isValid = performDeleteLineValidation(view, collectionGroup, deleteLine); 181 if (isValid) { 182 ((List<Object>) collection).remove(lineIndex); 183 processAfterDeleteLine(view, collectionPath, model, lineIndex); 184 } 185 } else { 186 logAndThrowRuntime("Only List collection implementations are supported for the delete by index method"); 187 } 188 } 189 190 /** 191 * In the case of edit maintenance deleted the item on the old side. 192 * This method is intended to override the method in MaintainableImpl 193 * but has a different set of parameters, so it is not actually an override. 194 * This was needed to fetch the old collection from a different path 195 * than MaintainableImpl uses. This version has the path (to the newMaintainableObject 196 * provided as a parameter, this is used to generate a path to the oldMaintainableObject 197 * 198 * 199 * @see org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl#processAfterDeleteLine(View, 200 * org.kuali.rice.krad.uif.container.CollectionGroup, java.lang.Object, int) 201 */ 202 protected void processAfterDeleteLine(View view, String collectionPath, Object model, int lineIndex) { 203 204 // Check for maintenance documents in edit 205 if (model instanceof MaintenanceForm && KRADConstants.MAINTENANCE_EDIT_ACTION.equals(((MaintenanceForm)model).getMaintenanceAction())) { 206 207 // get the old object's collection 208 String oldCollectionPath = collectionPath.replace("newMaintainableObject","oldMaintainableObject"); 209 Collection<Object> oldCollection = ObjectPropertyUtils.getPropertyValue(model, oldCollectionPath); 210 try { 211 // Remove the object at lineIndex from the collection 212 oldCollection.remove(oldCollection.toArray()[lineIndex]); 213 } catch (Exception e) { 214 throw new RuntimeException("Unable to delete line instance for old maintenance object", e); 215 } 216 } 217 } 218 219 220 }