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